Articles /

layout

aspect-ratio: replacing the padding hack

One property to enforce proportional dimensions. No more padding-top percentages, no more wrapper divs.

The old padding hack

Before aspect-ratio, the only way to maintain proportions was to exploit the fact that padding-top percentages are relative to the element's width. A 16:9 container required padding-top: 56.25% with a positioned child. It worked, but it was fragile and unintuitive.

/* The old way — don't do this anymore */
.video-wrapper {
  position: relative;
  padding-top: 56.25%; /* 9 / 16 = 0.5625 */
}
.video-wrapper > iframe {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}

The modern syntax

The aspect-ratio property accepts a ratio as width / height. The element's height is automatically computed from its width:

.video-wrapper {
  aspect-ratio: 16 / 9;
  inline-size: 100%;
}

.square-avatar {
  aspect-ratio: 1;          /* shorthand for 1 / 1 */
  inline-size: 3rem;
  border-radius: 50%;
}

.golden-card {
  aspect-ratio: 1.618 / 1;  /* golden ratio */
}
When both width and height are set explicitly, aspect-ratio is ignored. It only applies when at least one dimension is auto.

Images and object-fit

Images have a natural aspect ratio from their file dimensions. Setting aspect-ratio on an image overrides that natural ratio. Combine it with object-fit to control how the image fills the box:

.thumbnail {
  aspect-ratio: 4 / 3;
  inline-size: 100%;
  object-fit: cover;       /* crops to fill */
  object-position: center;
  border-radius: 0.5rem;
}

.contain-img {
  aspect-ratio: 16 / 9;
  object-fit: contain;     /* letterboxes to fit */
  background: oklch(0.2 0 0);
}

Responsive media containers

For embedded media like iframes and videos, aspect-ratio on the container eliminates layout shift before the content loads:

.embed {
  aspect-ratio: 16 / 9;
  inline-size: 100%;
  background: oklch(0.15 0 0);
  border-radius: 0.75rem;
  overflow: hidden;
}

.embed > iframe {
  inline-size: 100%;
  block-size: 100%;
  border: none;
}

This also works beautifully with content-visibility: auto — the browser knows the exact dimensions even before rendering the content.

Constraints with min and max

The aspect-ratio property respects min-height and max-height. If content exceeds the ratio-computed height, the element grows to contain it by default:

.card {
  aspect-ratio: 3 / 4;
  min-block-size: 200px;
  max-block-size: 600px;
}

/* Prevent overflow — clip to the ratio */
.strict-ratio {
  aspect-ratio: 1;
  overflow: hidden;
}
Content that overflows the computed height will stretch the element beyond its ratio. Add overflow: hidden if you need the ratio to be strict.

Grid and aspect-ratio

Combine aspect-ratio with CSS Grid for uniform card layouts where each item maintains the same proportions regardless of content length:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}

.gallery > img {
  aspect-ratio: 1;
  inline-size: 100%;
  object-fit: cover;
  border-radius: 0.25rem;
}