Keeping elements at a consistent width-to-height ratio used to require a messy padding hack. The CSS aspect-ratio property replaces all of that with a single clean declaration. This guide covers the syntax, common use cases, and how aspect-ratio interacts with other CSS properties.

The syntax

The property takes a ratio written as two numbers separated by a forward slash:

.box {
  aspect-ratio: 16 / 9;
}

/* A single number is treated as width / 1 */
.square {
  aspect-ratio: 1; /* same as 1 / 1 */
}

The browser calculates the missing dimension automatically. Set a width and the height is calculated from the ratio. Set a height and the width is calculated instead.

How the math works: with aspect-ratio: 16 / 9 and a width of 640px, the browser sets height to 640 * (9/16) = 360px automatically.

Common ratios and their uses

RatioCommon useExample
1 / 1SquareAvatar images, icon containers
16 / 9Widescreen videoYouTube embeds, hero videos
4 / 3Classic screen ratioOlder video content, thumbnails
3 / 2PhotographyBlog post images, photo galleries
2 / 1Wide bannerHero sections, billboard ads
9 / 16Vertical videoMobile stories, TikTok-style content

Replacing the padding-top hack

Before aspect-ratio existed, developers used a padding trick to maintain ratios on responsive containers. If you have seen this pattern in older codebases, here is what it was doing:

/* Old approach - the padding-top hack */
.video-wrapper {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 9/16 = 56.25% */
}
.video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* Modern approach - one line */
.video-wrapper {
  aspect-ratio: 16 / 9;
  width: 100%;
}
.video-wrapper iframe {
  width: 100%;
  height: 100%;
}

The padding hack worked because percentage padding is calculated from the element's width, not its height. It was a workaround, not a solution. aspect-ratio is the actual solution.

Responsive images with aspect-ratio

Combining aspect-ratio with object-fit gives you full control over how images fill a container without distortion:

.card-image {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover; /* fills the box, crops to fit */
  border-radius: 8px;
}

.avatar {
  width: 48px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
}

Without aspect-ratio, images with different natural dimensions would produce inconsistent card heights across a grid. With it, every card image is exactly the same shape regardless of the source image dimensions.

aspect-ratio with width and height both set

When you set both width and height explicitly, aspect-ratio is ignored - the element uses the dimensions you set directly. The property only applies when one dimension is determined automatically.

.box {
  width: 200px;
  height: 200px; /* explicit height - aspect-ratio is ignored */
  aspect-ratio: 16 / 9; /* has no effect here */
}

.box {
  width: 200px;
  /* no explicit height - aspect-ratio calculates it */
  aspect-ratio: 16 / 9; /* height = 112.5px */
}

Watch out for content overflow: if the content inside an element is taller than the height calculated by aspect-ratio, the content overflows. Use min-height instead of height when the content is dynamic.

aspect-ratio in a card grid

One of the most practical uses is keeping cards in a grid visually consistent when their content varies:

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

.card-thumbnail {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #1a1d27; /* fallback while image loads */
}

Using aspect-ratio for skeleton loaders

Skeleton loading states need a placeholder that matches the eventual content size. aspect-ratio makes this reliable without hardcoding heights:

.skeleton-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: linear-gradient(90deg, #1a1d27 25%, #2d3148 50%, #1a1d27 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 8px;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

aspect-ratio with min-height for flexible containers

When an element may receive more content than the ratio allows, use min-height: 0 or pair with overflow to control what happens:

.flexible-card {
  width: 100%;
  aspect-ratio: 4 / 3;
  /* Allow card to grow if content needs more space */
  height: auto;
  min-height: 0;
  overflow: hidden;
}

Browser support

The aspect-ratio property has full support in all modern browsers. Chrome 88, Firefox 89, Safari 15, and Edge 88 all support it. The only browsers that do not are Internet Explorer and very old mobile browsers.

If you need to support older browsers, you can use the padding-top hack as a fallback with @supports:

/* Fallback for older browsers */
.video-wrapper {
  position: relative;
  padding-top: 56.25%;
}

/* Override with modern property where supported */
@supports (aspect-ratio: 1) {
  .video-wrapper {
    padding-top: 0;
    aspect-ratio: 16 / 9;
  }
}

For most projects in 2026: IE is not a concern. Skip the fallback unless you have analytics showing significant traffic from legacy browsers. Use aspect-ratio directly.

Quick reference

ValueWhat it does
aspect-ratio: 16 / 9Sets a 16:9 ratio, height calculated from width
aspect-ratio: 1Forces a square (shorthand for 1/1)
aspect-ratio: autoUses the element's intrinsic ratio (default for images)
aspect-ratio: auto 3 / 2Uses intrinsic ratio if available, falls back to 3/2

Generate CSS box shadows visually

Use our free Box Shadow Generator to build and preview shadows in real time - no manual tweaking needed.

Open Box Shadow Generator →