Shawn Spencer
Shawn Spencer

Reputation: 1460

How to apply (S)CSS aspect ratio to images of varied sizes?

In one of my page layouts I have cards, side by side. Each card has a title, an image and a short description. Someone from QA created an outlier case and tossed an image with highly irregular dimensions in the mix. The boss can't be persuaded to fix the one or two images that actually exist in production. Instead, I now need to come up with a solution that will affect all images.

Here's the layout, simplified:

enter image description here

For simplicity's sake, 99.9% of the images are 300px wide and 200px high.

QA throws in an image that is 1000px wide and 1000px high.

The following works in some situations:

@media screen and (max-width: 1024px) {
  .the-card-image {
    width: 100%;
    -o-object-fit: cover;
    object-fit: cover;
    -o-object-position: center;
    object-position: center;
    max-height: $btmimglgh;
    min-height: $btmimgsmh;
    max-width: $btmimglgw;
    min-width: $btmimgsmw;
  }
}

Miraculously – in this actual scenario – all images have the same height and width. None of the enclosing container (the blue-ish boxes) have any set width or height. Their width is based on a percentage.

The max-height and max-width are the tallest dimensions that the images can get (via Inspector). And the min-height and the min-width are the smallest dimensions.

However, there has to be a better way to do that, right?

I have tried position: absolute; bottom: 0; left: 0; right: 0; top: 0; on the image to no avail. I have to support older web browsers, so I cannot use aspect-ratio (which is still experimental).

Can anyone think of a "smart way" to do that – I am obviously not able to figure this one out.

.

Upvotes: 0

Views: 724

Answers (1)

ray
ray

Reputation: 27245

Here's a working example implementation of the padding hack technique I mentioned in my comment.

Notice that one image is 300x200 and the other 1000x1000, but both conform to the 3x2 aspect ratio. The latter image gets clipped at top and bottom as necessary.

.image-container {
  /* establish positioning context for the img */
  position: relative;
  
  /* establish a 3x2 aspect ratio */
  height: 0;
  padding-top: 66.6666%;
  
  /* clip overflow */
  overflow: hidden;
}

.image-container > img {
  /* limit image to 100% width */
  max-width: 100%;
  
  /* pin to the container's bounds */
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  
  /* ensure it covers the available area, possibly
  some clipping if aspect ratio doesn't match */
  object-fit: cover;
}

/* the rest is purely cosmetic */

.container {
  display: flex;
  font-family: sans-serif;
}

.card {
  border-radius: 4px;
  width: 300px;
  box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.125);
  padding: 0.5rem 1rem 1rem;
  margin: 0.5rem;
}
<div class="container">
  <div class="card">
    <h3>300 x 200 Sollicitudin Magna</h3>
    <div class="image-container">
      <img src="//placekitten.com/300/200" />
    </div>
    <p>
      Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Nullam quis risus eget urna mollis ornare vel eu leo.
    </p>
  </div>

  <div class="card">
    <h3>1000 x 1000 Sollicitudin Magna</h3>
    <div class="image-container">
      <img src="//placekitten.com/1000/1000" />
    </div>
    <p>
      Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Nullam quis risus eget urna mollis ornare vel eu leo.
    </p>
  </div>
</div>

Upvotes: 1

Related Questions