Keep an Image in Aspect Ratio

What could be more satisfying that this: The image size changes, but the image is kept in the correct aspect ratio so that its shape doesn't get distorted

Flexible Images

In the era of a bajillion + 1 viewport sizes, many images on your site will grow or shrink with the space available to them.

Aspect Ratio

The aspect ratio of an image (or any other 2D doohicky) is the relative size between the horizontal length and vertical height. A common aspect ratio for a film is 16:9.

Easy Street

In the best, easiest case, you don't need anything fancy at all to keep aspect ratio on your images. Only constrain one side, either the horizontal or vertical measurement of your image, and the other will grow or shrink proportionally.

Scenario with Some Constraints

But some scenarios don't allow simply setting the horizontal width and calling it a day. One such scenario:

I have an image in a container, where the image is set to cover that container with object-fit: cover. And that container is flexing, say, in a display: grid column of 1fr.

Let's address the technique for that scenario.

Image Container Defines the Aspect Ratio

In this case, we're using a container parent node to constrain the image. This is because some images are flatter and wider, some are taller and thinner. But in this design, we want all images to have the same aspect ratio. The container parent node, not the image itself, describes the dimension. So, just setting the width of the image and auto scaling won't work.

The HTML we're looking for is something like this:

<div class="keep-aspect-ratio">
  <img class="fit-into-aspect-ratio" src="some-image.jpg" />
</div>

Modern CSS: aspect-ratio

Let's style the parent container. CSS provides the answer with a beautiful attribute aspect-ratio. Set the ratio with something like this:

.keep-aspect-ratio {
  aspect-ratio: 16 / 9;
}
.fit-into-aspect-ratio {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Props to Max for making sure we use the easy way.

If the year is 2021 or greater, stop here.

Old CSS Hack: padding-bottom

Before the days of aspect-ratio, there was a limitation: Setting percentage height on the container didn't work. It was a CSS limitation. It wouldn't maintain aspect ratio.

We could set a width for the container (eg, 100% of the column), but setting a percentage height wouldn't work. So we set a vertical space that could use percentages: padding.

We set padding-bottom on the parent node instead and set all other height-related attributes to zero in order to avoid increasing the vertical space without meaning to.

To find the correct percentage for a 16:9 aspect ratio, we divide 9/16, and get .5625. Our padding percentage is 56.25%. We also have to position the parent relative and then the child image absolute inside of it, filling the space fully.

To style the container and image, the CSS looks like this:

.keep-aspect-ratio {
  position: relative;
  display: block;
  height: 0;
  line-height: 0;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
}
.fit-into-aspect-ratio {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

And the dance goes like this... EOF