SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/aspect-ratio

7 CSS Aspect Ratio Demos

6 Pure CSS1 with JSPublished 2026-10-05Free · no sign-up

Seven demos of the aspect-ratio property: a 16:9 video frame, square tiles sized by their column, object-fit cover and contain compared, card thumbnails kept in line, a frame that switches ratio, a box that grows when content needs it and the old padding hack beside the modern one-liner.

01. Responsive 16:9 Video Frame

aspect-ratioVideo

aspect-ratio: 16 / 9 on the frame keeps any embedded video at the right shape at every width, replacing the old padding-top: 56.25% trick. The iframe or video simply fills it with width and height at 100 percent.

View code
<figure class="ar1"><div class="fr"><div class="vid" role="img" aria-label="Video placeholder">▶</div></div><figcaption>16 / 9 at any width</figcaption></figure>
.ar1 { width: 420px; max-width: 100%; margin: 0; font: 13px Inter, system-ui, sans-serif; color: #94a3b8; }
.ar1 .fr { aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden; background: #000; }
.ar1 .vid { display: grid; place-items: center; width: 100%; height: 100%; background: linear-gradient(135deg, #1e293b, #334155); color: #fff; font-size: 36px; }
.ar1 figcaption { margin-top: 6px; }

02. Square Tiles at Any Width

aspect-ratioGrid

A grid of perfectly square tiles whose size comes from the column width: each tile only sets aspect-ratio: 1. Resize the preview and the tiles stay square without a single height in the CSS.

View code
<ul class="ar2"><li>A</li><li>B</li><li>C</li><li>D</li><li>E</li><li>F</li></ul>
.ar2 { display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 8px; width: 360px; max-width: 100%; margin: 0; padding: 0; list-style: none; font: 800 20px Inter, system-ui, sans-serif; }
.ar2 li { display: grid; place-items: center; aspect-ratio: 1; border-radius: 12px; background: #eef4ff; color: #1e3a8a; }
.ar2 li:nth-child(3n) { background: #fdf2fa; color: #9e165f; } .ar2 li:nth-child(3n+2) { background: #ecfdf3; color: #054f31; }

03. object-fit: cover vs contain

aspect-ratioImages

The same wide image in two square frames: cover fills the frame and crops the sides, contain fits the whole image and leaves bars. Images inside fixed-ratio frames almost always want cover, with object-position to choose which part is kept.

View code
<div class="ar3"><figure><img alt="Wide striped test image cropped to fill the square" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 120'%3E%3Crect width='300' height='120' fill='%230ea5e9'/%3E%3Crect width='100' height='120' fill='%23f59e0b'/%3E%3Crect x='200' width='100' height='120' fill='%23db2777'/%3E%3C/svg%3E" style="object-fit:cover"><figcaption>cover</figcaption></figure><figure><img alt="The same image shown whole with empty bars" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 120'%3E%3Crect width='300' height='120' fill='%230ea5e9'/%3E%3Crect width='100' height='120' fill='%23f59e0b'/%3E%3Crect x='200' width='100' height='120' fill='%23db2777'/%3E%3C/svg%3E" style="object-fit:contain"><figcaption>contain</figcaption></figure></div>
.ar3 { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; font: 600 13px "JetBrains Mono", ui-monospace, monospace; color: #475467; }
.ar3 figure { margin: 0; text-align: center; }
.ar3 img { display: block; width: 130px; aspect-ratio: 1; border-radius: 12px; background: #e4e7ec; }
.ar3 figcaption { margin-top: 6px; }

04. Card Thumbnails Kept in Line

aspect-ratioCards

Uploaded images come in all shapes, which makes card grids ragged. Giving every thumbnail the same aspect-ratio with object-fit: cover lines up the titles under them, whatever the original photos look like.

View code
<ul class="ar4"><li><span class="th" style="--g:linear-gradient(135deg,#f97316,#7c2d12)"></span>Tall original</li><li><span class="th" style="--g:linear-gradient(90deg,#22d3ee,#1e3a8a)"></span>Wide original</li><li><span class="th" style="--g:linear-gradient(135deg,#a3e635,#14532d)"></span>Square original</li></ul>
.ar4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; width: 420px; max-width: 100%; margin: 0; padding: 0; list-style: none; color: #e2e8f0; font: 600 13px Inter, system-ui, sans-serif; }
.ar4 li { display: grid; gap: 6px; }
.ar4 .th { aspect-ratio: 4 / 3; border-radius: 10px; background: var(--g); }

05. Switch Between Ratios

aspect-ratioInteractive

Buttons change one custom property and the frame snaps between 1:1, 4:3 and 16:9, showing how one variable can drive the shape of a media frame. The buttons form a group with the current ratio pressed.

View code
<div class="ar5"><div class="bar" role="group" aria-label="Aspect ratio"><button aria-pressed="true" data-r="1 / 1">1:1</button><button aria-pressed="false" data-r="4 / 3">4:3</button><button aria-pressed="false" data-r="16 / 9">16:9</button></div><div class="fr"><span>1 / 1</span></div></div>
.ar5 { width: 260px; max-width: 100%; font-family: Inter, system-ui, sans-serif; }
.ar5 .bar { display: flex; gap: 6px; margin-bottom: 10px; }
.ar5 button { flex: 1; padding: 8px; border: 1px solid #d0d5dd; border-radius: 8px; background: #fff; font: 700 13px Inter, system-ui, sans-serif; cursor: pointer; }
.ar5 [aria-pressed=true] { background: #101828; color: #fff; border-color: #101828; }
.ar5 button:focus-visible { outline: 3px solid #84adff; outline-offset: 2px; }
.ar5 .fr { --r: 1 / 1; display: grid; place-items: center; aspect-ratio: var(--r); border-radius: 12px; background: linear-gradient(135deg, #c7d2fe, #6366f1); color: #fff; font: 800 18px "JetBrains Mono", ui-monospace, monospace; transition: aspect-ratio .3s; }
var fr = document.querySelector('.ar5 .fr'), bs = document.querySelectorAll('.ar5 button');
bs.forEach(function (b) { b.onclick = function () { bs.forEach(function (x) { x.setAttribute('aria-pressed', x === b); }); fr.style.setProperty('--r', b.dataset.r); fr.querySelector('span').textContent = b.dataset.r; }; });

06. Ratio as a Minimum, Not a Cage

aspect-ratioContent

aspect-ratio sets a preferred shape, but a box with text inside grows taller when the text needs room, because its minimum height is auto. The second card has more text and quietly breaks the ratio instead of overflowing, which is usually what you want.

View code
<div class="ar6"><article><b>Short</b>Fits the 4:3 shape.</article><article><b>Long</b>This card has a lot more to say, so it grows past the 4:3 shape rather than letting the text spill out of the box, because aspect-ratio respects content by default.</article></div>
.ar6 { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; align-items: start; width: 380px; max-width: 100%; font: 13px/1.45 Inter, system-ui, sans-serif; }
.ar6 article { aspect-ratio: 4 / 3; padding: 12px; box-sizing: border-box; border: 1px dashed #64748b; border-radius: 12px; background: #151b2e; color: #cbd5e1; }
.ar6 b { display: block; margin-bottom: 4px; color: #fff; }

07. Old Padding Hack vs aspect-ratio

aspect-ratioLegacy

Side by side, the padding-top percentage hack and the modern property produce the same 3:2 box. The hack needed an extra wrapper and absolute positioning; aspect-ratio needs one line. Keep the hack only if you must support very old browsers.

View code
<div class="ar7"><figure><div class="old"><span>padding-top: 66.67%</span></div><figcaption>Before</figcaption></figure><figure><div class="new"><span>aspect-ratio: 3 / 2</span></div><figcaption>After</figcaption></figure></div>
.ar7 { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; width: 360px; max-width: 100%; font: 600 11px "JetBrains Mono", ui-monospace, monospace; }
.ar7 figure { margin: 0; } .ar7 figcaption { margin-top: 6px; color: #475467; font-family: Inter, system-ui, sans-serif; font-size: 13px; }
.ar7 .old { position: relative; padding-top: 66.67%; border-radius: 10px; background: #fef0c7; }
.ar7 .old span { position: absolute; inset: 0; display: grid; place-items: center; color: #93370d; text-align: center; padding: 6px; }
.ar7 .new { display: grid; place-items: center; aspect-ratio: 3 / 2; padding: 6px; box-sizing: border-box; border-radius: 10px; background: #d1fadf; color: #054f31; text-align: center; }

About these CSS Aspect Ratio Demos

One line replaces a hack

aspect-ratio: 16 / 9 keeps a box's shape as its width changes. It replaces the padding-top percentage trick, which needed an extra wrapper and absolutely positioned content.

Pair it with object-fit

An image in a fixed-ratio frame should use object-fit: cover to fill it and crop the overflow, or contain to show the whole image with bars. object-position picks which part survives the crop.

It prevents layout shift

Images with width and height attributes get an automatic aspect ratio before they load, so the page does not jump when they arrive. Set the attributes on every image.

Content still wins

If text inside a box needs more height than the ratio allows, the box grows, because its minimum height is auto. Add overflow: auto or min-height: 0 only if you really want a fixed shape.

Frequently asked questions

Is aspect-ratio supported everywhere?

Yes, in all current browsers.

What ratio should product images use?

Pick one, often 1:1 or 4:5, and use it everywhere so grids line up.

Can I animate aspect-ratio?

Yes, it is animatable, though changing it reflows the layout, so use it sparingly.