1

example

I am trying to cut a rectangle from the image. Please tell me the best way to do this. I need to support IE 11. (without clip-path).

I already tried to do it, but not very happy with the result.

body {
  margin: 0;
}

.block {
  height: 400px;
  display: flex;
}

.block-image,
.block:before,
.block:after {
  content: "";
  position: relative;
  height: 100%;
  background-image: url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80");
  background-size: 100vw auto;
  background-repeat: no-repeat;
}

.block:before {
  top: 50px;
  flex: auto;
  background-position: left top -50px;
}

.block:after {
  flex: auto;
  background-position: right top;
}

.block-image {
  flex: 1 1 300px;
  max-width: 300px;
  background-position: center top;
}
<div class="block">
  <div class="block-image"></div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Taras Gordienko
  • 161
  • 2
  • 3
  • 15
  • 1
    Is using a photo editor like Photoshop in order to crop the image out of the question? – wouch Feb 26 '20 at 15:42
  • please clarify what you mean by "cut a rectangle from the image". is positioning a solid color rectangle over top of the image sufficient, or does it need to actually have a transparent void so that whatever is behind the image can show through? – Woodrow Barlow Feb 26 '20 at 20:42
  • @TemaniAfif you use safari without scrollbar width, so you don’t see a problem) My final result https://codepen.io/razrabotal/pen/MWwpBKo . Thanks a lot Temani Afif, I added some math to your answer – Taras Gordienko Feb 26 '20 at 21:11
  • 1
    @TarasGordienko check my update ;) I was also working on some maths – Temani Afif Feb 26 '20 at 21:15

1 Answers1

2

I would optimize the code like below:

body {
  margin: 0;
  background:pink;
}

.block {
  margin:50px 0;
  height: 400px;
  background:url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80") no-repeat;
  background-size:0 0;
}

.block:before,
.block:after {
  content: "";
  float:left;
  height: 100%;
  background: inherit;
}

.block:before {
  width:30%;
  background-size:333.33% auto; /* 100%/0.3 */
  background-position:left 0 top 0;
  transform:translateY(-50px);
}

.block:after {
  width:70%;
  background-size:142.85% auto; /* 100%/0.7 */
  background-position:right 0 top -50px;
}
<div class="block">
</div>

To have the image centred:

body {
  margin: 0;
  background:pink;
}

.block {
  margin:50px 0;
  height: 400px;
  background:url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80") no-repeat;
  background-size:0 0;
}

.block:before,
.block:after {
  content: "";
  float:left;
  height: 100%;
  background: inherit;
}

.block:before {
  width:30%;
  background-size:333.33% auto; /* 100%/0.3 */
  background-position:left center;
  transform:translateY(-50px);
}

.block:after {
  width:70%;
  background-size:142.85% auto; /* 100%/0.7 */
  background-position:right 0 top calc(50% - 50px);
}
<div class="block">
</div>

If you want a bigger width for the image:

body {
  margin: 0;
  background:pink;
}

.block {
  margin:50px 0;
  height: 400px;
  background:url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80") no-repeat;
  background-size:0 0;
}

.block:before,
.block:after {
  content: "";
  float:left;
  height: 100%;
  background: inherit;
}

.block:before {
  width:30%;
  background-size:500% auto; /* 150%/0.3 */
  background-position:left 25% top 50%;
  transform:translateY(-50px);
}

.block:after {
  width:70%;
  background-size:214.275% auto; /* 150%/0.7 */
  background-position:right 25% top calc(50% - 50px);
}
<div class="block">
</div>

Here is a more generic solution using CSS variables and calc(). I know you want to support IE but this only for demo purpose and you can easily use the calculated values like the examples above:

body {
  margin: 0;
  background:pink;
}

.block {
  --w:0.3;  /* width of left part (without unit and from 0 to 1 (1 = 100%) )*/
  --h:50px; /* height of the cut*/
  --s:1.5;  /* scale factor of the image (1 = 100% width of container)*/
  
  margin:calc(var(--h) + 10px) 0;
  height: 400px;
  background:url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80") 0/0 no-repeat;
}

.block:before,
.block:after {
  content: "";
  float:left;
  height: 100%;
  background: inherit;
}

.block:before {
  width:calc(var(--w)*100%);
  background-size:calc(var(--s) * (100%/var(--w)))  auto;
  background-position:
    left calc( 
          100% *
           ( (var(--s) - 1) /
             (2* (var(--s) - var(--w)) ) 
           ) 
          ) 
     top 50%;
  transform:translateY(calc(-1*var(--h)));
}

.block:after {
  width:calc(100%*(1 - var(--w)));
  background-size:calc(var(--s) * (100%/(1 - var(--w)))) auto;
  background-position:
   right calc( 
          100% *
           ( (var(--s) - 1) /
             (2* (var(--s) - 1 + var(--w)) ) 
           ) 
          )
   top calc(50% - var(--h));
}
<div class="block">
</div>

<div class="block" style="--s:2;--h:100px;--w:0.5">
</div>

<div class="block" style="--s:1.75;--h:150px;--w:0.8">
</div>

<div class="block" style="--s:3;--h:30px;--w:0.7">
</div>

The calculation of the position is a bit complex, you may refer to the following question to understand how it works: Using percentage values with background-position on a linear-gradient



To keep this answer generic I will also consider the clip-path way which is the most logical one even if it's not supported by IE

body {
  margin: 0;
  background:pink;
}

.block {
  --w:30%;  /* width of left part */
  --h:50px; /* height of the cut*/
  
  margin:10px 0;
  height: 400px;
  background:url("https://images.unsplash.com/photo-1558980664-10e7170b5df9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80") center/cover no-repeat;
  
  clip-path:polygon(
   0 0,var(--w) 0,var(--w) var(--h),100% var(--h),
   100% 100%,var(--w) 100%,var(--w) calc(100% - var(--h)),0 calc(100% - var(--h)));
}
<div class="block">
</div>

<div class="block" style="--h:100px;--w:50%">
</div>

<div class="block" style="--h:150px;--w:80%">
</div>

<div class="block" style="--h:30px;--w:70%">
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415