2

I have an image with some text in a responsive column. The image is chosen by users so I don't know it's aspect ratio beforehand. I want to limit the height of the image to an aspect ratio of 1 / 1. This means :

  • Landscape images are shown fully
  • Portrait images should be cropped to a 1 / 1 aspect ratio and have the object-fit: cover; and object-position: center; behaviour

Here is a code example :

body {
  display: flex;
}
.container {
  width: 50%;
  padding: 0 5%;
}
.image-wrap img {
  width: 100%;
}
<div class="container">
  <h3>Landscape image</h3>
  <div class="image-wrap">
    <img src="https://placehold.co/400x200" />
  </div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In posuere elit sit amet ullamcorper feugiat. Etiam vitae venenatis est, tincidunt elementum nibh. Nunc volutpat maximus suscipit. Sed scelerisque neque in lorem pulvinar, vel mattis enim tristique. Morbi in sagittis justo. Donec in dui eget sem dapibus ultricies. Vestibulum vel nunc eget nisl hendrerit placerat a sed tellus. Vivamus convallis nec felis semper rutrum. Curabitur efficitur pellentesque nisi. Integer ut diam in risus condimentum sodales. Aenean bibendum congue metus, ut blandit sapien hendrerit eget. Proin tristique facilisis erat non scelerisque. Duis ornare, nunc ac faucibus mollis, nisi felis dapibus justo, ut maximus dui magna vel quam. Nam molestie luctus lectus, et viverra ante dapibus vel.</p>
</div>
<div class="container">
  <h3>portrait image</h3>
  <div class="image-wrap">
    <img src="https://placehold.co/400x600" />
  </div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In posuere elit sit amet ullamcorper feugiat. Etiam vitae venenatis est, tincidunt elementum nibh. Nunc volutpat maximus suscipit. Sed scelerisque neque in lorem pulvinar, vel mattis enim tristique. Morbi in sagittis justo. Donec in dui eget sem dapibus ultricies. Vestibulum vel nunc eget nisl hendrerit placerat a sed tellus. Vivamus convallis nec felis semper rutrum. Curabitur efficitur pellentesque nisi. Integer ut diam in risus condimentum sodales. Aenean bibendum congue metus, ut blandit sapien hendrerit eget. Proin tristique facilisis erat non scelerisque. Duis ornare, nunc ac faucibus mollis, nisi felis dapibus justo, ut maximus dui magna vel quam. Nam molestie luctus lectus, et viverra ante dapibus vel.</p>
</div>

The behaviour I need for images exceeding the 1/1 apsect ratio is :

body {
  display: flex;
}

.container {
  width: 50%;
  padding: 0 5%;
}

.image-wrap {
  aspect-ratio: 1/1;
}

.image-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
<div class="container">
  <h3>portrait image</h3>
  <div class="image-wrap">
    <img src="https://placehold.co/400x600" />
  </div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In posuere elit sit amet ullamcorper feugiat. Etiam vitae venenatis est, tincidunt elementum nibh. Nunc volutpat maximus suscipit. Sed scelerisque neque in lorem pulvinar, vel mattis enim tristique. Morbi in sagittis justo. Donec in dui eget sem dapibus ultricies. Vestibulum vel nunc eget nisl hendrerit placerat a sed tellus. Vivamus convallis nec felis semper rutrum. Curabitur efficitur pellentesque nisi. Integer ut diam in risus condimentum sodales. Aenean bibendum congue metus, ut blandit sapien hendrerit eget. Proin tristique facilisis erat non scelerisque. Duis ornare, nunc ac faucibus mollis, nisi felis dapibus justo, ut maximus dui magna vel quam. Nam molestie luctus lectus, et viverra ante dapibus vel.</p>
</div>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • Still didn't get what behavior you are expecting? What do you mean by "The behaviour I need for images exceeding the 1/1 apsect ratio is"? – Nexo May 11 '23 at 15:51
  • @Nikkkshit the images exceeding the 1/1 aspect ratio should be cropped to a square, fill the square completly and be centered in the square. That is the behaviour you get when you ues `object-fit: cover;` and `object-position: center;` on the image and `aspect-ratio : 1 / 1;` on it's container. – web-tiki May 11 '23 at 15:54

2 Answers2

1

This is a use case for the new container query units. Here you can use cqw as max-height

body {
  display: flex;
}
.container {
  width: 50%;
  padding: 0 5%;
  container-type: inline-size; /* we make this a container */
}
.image-wrap {

}

.image-wrap img {
  width: 100%;
  max-height: 100cqw; /* don't exceed 100% width of the container */
  object-fit: cover;
}
<div class="container">
  <h3>Landscape image</h3>
  <div class="image-wrap">
    <img src="https://placehold.co/400x200" />
  </div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In posuere elit sit amet ullamcorper feugiat. Etiam vitae venenatis est, tincidunt elementum nibh. Nunc volutpat maximus suscipit. Sed scelerisque neque in lorem pulvinar, vel mattis enim tristique. Morbi in sagittis justo. Donec in dui eget sem dapibus ultricies. Vestibulum vel nunc eget nisl hendrerit placerat a sed tellus. Vivamus convallis nec felis semper rutrum. Curabitur efficitur pellentesque nisi. Integer ut diam in risus condimentum sodales. Aenean bibendum congue metus, ut blandit sapien hendrerit eget. Proin tristique facilisis erat non scelerisque. Duis ornare, nunc ac faucibus mollis, nisi felis dapibus justo, ut maximus dui magna vel quam. Nam molestie luctus lectus, et viverra ante dapibus vel.</p>
</div>
<div class="container">
  <h3>portrait image</h3>
  <div class="image-wrap">
    <img src="https://placehold.co/400x600" />
  </div>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In posuere elit sit amet ullamcorper feugiat. Etiam vitae venenatis est, tincidunt elementum nibh. Nunc volutpat maximus suscipit. Sed scelerisque neque in lorem pulvinar, vel mattis enim tristique. Morbi in sagittis justo. Donec in dui eget sem dapibus ultricies. Vestibulum vel nunc eget nisl hendrerit placerat a sed tellus. Vivamus convallis nec felis semper rutrum. Curabitur efficitur pellentesque nisi. Integer ut diam in risus condimentum sodales. Aenean bibendum congue metus, ut blandit sapien hendrerit eget. Proin tristique facilisis erat non scelerisque. Duis ornare, nunc ac faucibus mollis, nisi felis dapibus justo, ut maximus dui magna vel quam. Nam molestie luctus lectus, et viverra ante dapibus vel.</p>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Nice one ! Unfortunatly browser support isn't good enough for my target users. The `cwp` unit doesn't work with `max-width` in Firefox 114 (although it works with `width`). I guess I'll have to workout the image aspect ratio server side to add a class to portrait images. – web-tiki May 12 '23 at 08:23
  • 1
    @web-tiki it should work in Firefox. The code was a bit complex but It's updated with another version now. The display grid trick was not working fine on FF – Temani Afif May 12 '23 at 08:27
  • Indeed, is works in FF now ! – web-tiki May 12 '23 at 08:36
-1
Try this. It works for me. 

<div class="wrapper"> /*stand-in for body*/
   <div class="container"> 
       <div class="image-wrap">
           <h3>Landscape image</h3>
           <img src="https://placehold.co/400x200" alt="image">                 
       </div>
       <div class="image-wrap">
           <h3>portrait image</h3>
           <img src="https://placehold.co/400x600" alt"image">
       </div>
   </div>
</div>

.wrapper {
    display: flex;
    flex-flow: column wrap;
}

.container {
    width: 50%;
    padding: 0 5%;
}
.image-wrap {
    /*set image width as needed for layout
    set desired landscape aspect-ratio. This will create a slot/box/area to hold the image
    position the image slot in page layout */

    width: 35vw; //or whatever
    aspect-ratio: 16 / 9; //sizes the final image displayed  
    // add positioning css - top, left, margin, padding, etc
}
.image-wrap > img {
    /*set width to 100% of image-wrap width
    object-position not needed: center is the default*/
    width: 100%;
    height: 100%;
    object-fit: cover;
}
dougl
  • 1
  • 2