I am trying to figure out, if there is any way to resize the clipped part of the image with use of css. In the most expected version, image resized this way should keep the imposed aspect ratio.
I was playing with clip-path, trying both approaches (svg & inset()), as well as working around object-position & object-fit parameters, unfortunately I can not achieve expected result :(
Here is my actual code. I need the clipped image to fit the size of the picture element (the background of picture should be covered by the clipped image)
CASE STUDY https://i.sstatic.net/Vx3Md.jpg
picture {
position: relative;
display: block;
width: 100%;
height: auto;
overflow: hidden;
background: #ddd;
}
picture.ratio-3-4 {
padding-top: 133.3%;
}
picture img.clip {
position: absolute;
top: 0;
left: 0;
-webkit-clip-path: inset(0 33.7% 7.6% 0);
clip-path: inset(0 33.7% 7.6% 0);
}
<picture class="ratio-3-4">
<img src="https://images.unsplash.com/photo-1551927336-09d50efd69cd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2710&q=80" class="clip" alt="">
</picture>
Here is an idea of a calculation to translate the value of the clip-path and use them with top/left and height/width. I considered CSS variables so you can easily understand the logic and compare with both method. I considered uniteless value and later will add the percentage in the calculate.
:root {
--top:5;
--left:10;
--right:10;
--bottom:10;
}
picture {
position: relative;
display: inline-block;
width: 300px;
overflow: hidden;
background: #ddd;
border:2px solid red;
}
picture.ratio-3-4::before {
content:"";
display:block;
padding-top: 133.3%;
}
picture.ratio-1-1::before {
content:"";
display:block;
padding-top: 100%;
}
picture img.clip {
position: absolute;
top: calc((var(--top) *-100%)/ (100 - (var(--top) + var(--bottom)) ));
left: calc((var(--left)*-100%)/ (100 - (var(--left) + var(--right)) ));
width: calc(10000%/ (100 - (var(--left) + var(--right)) ));
height:calc(10000%/ (100 - (var(--top) + var(--bottom)) ));
}
img {
width:300px;
clip-path:
inset(calc(var(--top)*1%) calc(var(--right)*1%)
calc(var(--bottom)*1%) calc(var(--left)*1%) );
}
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
<picture class="ratio-3-4">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>
<picture class="ratio-1-1">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>
You simply need to adjust the values like you want:
:root {
--top:15;
--left:0;
--right:50;
--bottom:0;
}
picture {
position: relative;
display: inline-block;
width: 300px;
overflow: hidden;
background: #ddd;
border:2px solid red;
}
picture.ratio-3-4::before {
content:"";
display:block;
padding-top: 133.3%;
}
picture.ratio-1-1::before {
content:"";
display:block;
padding-top: 100%;
}
picture img.clip {
position: absolute;
top: calc((var(--top) *-100%)/ (100 - (var(--top) + var(--bottom)) ));
left: calc((var(--left)*-100%)/ (100 - (var(--left) + var(--right)) ));
width: calc(10000%/ (100 - (var(--left) + var(--right)) ));
height:calc(10000%/ (100 - (var(--top) + var(--bottom)) ));
}
img {
width:300px;
clip-path:
inset(calc(var(--top)*1%) calc(var(--right)*1%)
calc(var(--bottom)*1%) calc(var(--left)*1%) );
}
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip">
<picture class="ratio-3-4">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip">
</picture>
<picture class="ratio-1-1">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip">
</picture>
And later you can add them as inline style:
:root {
--top:15;
--left:0;
--right:50;
--bottom:0;
}
picture {
position: relative;
display: inline-block;
width: 300px;
overflow: hidden;
background: #ddd;
border:2px solid red;
}
picture.ratio-3-4::before {
content:"";
display:block;
padding-top: 133.3%;
}
picture img.clip {
position: absolute;
top: calc((var(--top) *-100%)/ (100 - (var(--top) + var(--bottom)) ));
left: calc((var(--left)*-100%)/ (100 - (var(--left) + var(--right)) ));
width: calc(10000%/ (100 - (var(--left) + var(--right)) ));
height:calc(10000%/ (100 - (var(--top) + var(--bottom)) ));
}
img {
width:300px;
clip-path:
inset(calc(var(--top)*1%) calc(var(--right)*1%)
calc(var(--bottom)*1%) calc(var(--left)*1%) );
}
<picture class="ratio-3-4" style="--top:10;--left:50;--bottom:10;--right:0">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>
<picture class="ratio-3-4" style="--top:10;--left:0;--bottom:10;--right:0">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>
<picture class="ratio-3-4" style="--top:0;--left:0;--bottom:50;--right:0">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip">
</picture>
If you want to work with pixel value you can adjust the code like below:
picture {
position: relative;
display: inline-block;
width: 300px;
overflow: hidden;
background: #ddd;
border:2px solid red;
}
picture.ratio-3-4::before {
content:"";
display:block;
padding-top: 133.3%;
}
picture img.clip {
position: absolute;
top: calc( -1*var(--top));
left: calc( -1*var(--left));
width: calc(100% + var(--left) + var(--right));
height:calc(100% + var(--top) + var(--bottom));
}
img {
width:300px;
clip-path:
inset(calc(var(--top)) calc(var(--right))
calc(var(--bottom)) calc(var(--left)) );
}
<picture class="ratio-3-4" style="--top:10px;--left:150px;--bottom:10px;--right:0px">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip">
</picture>
<picture class="ratio-3-4" style="--top:100px;--left:0px;--bottom:200px;--right:0px">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>
<picture class="ratio-3-4" style="--top:0px;--left:0px;--bottom:300px;--right:120px">
<img src="https://i.sstatic.net/5vZ65.jpg" class="clip" >
</picture>