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
| Ratio | Common use | Example |
|---|---|---|
| 1 / 1 | Square | Avatar images, icon containers |
| 16 / 9 | Widescreen video | YouTube embeds, hero videos |
| 4 / 3 | Classic screen ratio | Older video content, thumbnails |
| 3 / 2 | Photography | Blog post images, photo galleries |
| 2 / 1 | Wide banner | Hero sections, billboard ads |
| 9 / 16 | Vertical video | Mobile 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
| Value | What it does |
|---|---|
| aspect-ratio: 16 / 9 | Sets a 16:9 ratio, height calculated from width |
| aspect-ratio: 1 | Forces a square (shorthand for 1/1) |
| aspect-ratio: auto | Uses the element's intrinsic ratio (default for images) |
| aspect-ratio: auto 3 / 2 | Uses 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 →