TIL

Setting minimum height to an aspect-ratio in CSS

Let's set up the problem: You want a set of cards to display images in a square most of the time, like this:

A screenshot of a card with text that is very short, allowing for the design to work as intended.

But since content height might vary, you need to build defensively with CMS authors in mind, so the design should allow for longer content:

A screenshot of a card with text that is too long, breaking the layout.

Typically, we'd achieve this with a padding hack, or using pseudo-elements to fake a min-height that matches the width of the image. But now, it's safe to use container query units in production (See browser support).

First, define a container on the parent element of the image:

figure {
  container-type: size;
}

To use container units, you don't even have to use a container query. You just have to target an element that lives within the container, and then you can use the size of the container – both width and height – as a unit. So to make any aspect ratio a min-height, calculate the percentage of the height needed and apply it to the min-height value using the cqw ("container query width") unit. One cq unit is 1% of the entire value, so 100cqw would create a minimum value of "square" like this:

img {
  min-height: 100cqw;
  height: 100%;
  object-fit: cover;
}

Note that this assumes that figure is a grid cell, which is the quickest way to achieve two side-by-side items that fill the same amount of space.