15 CSS Aspect Ratio Demos09 / 15
CSS Aspect Ratio Dynamic Content Fallback
What happens when the words don't fit the ratio? This demo makes the aspect-ratio contract legible: it's a preferred size, not a promise. Default tiles bend — content-based minimum sizing lets long CMS copy grow the box past 16:9 instead of spilling. Strict tiles (min-height: 0) hold the ratio and scroll inside. And aspect-ratio: auto 3/2 gives images a placeholder shape that yields to their intrinsic one on arrival. Flip the 'verbose CMS' switch and watch each policy respond.
Published
The code
<section class="car-09" aria-label="Aspect ratio dynamic content fallback demo">
<div class="car-09__stage" id="car09-top">
<header class="car-09__bar">
<div>
<h1>The ratio is a preference, not a promise</h1>
<p>Three fallback policies for content nobody proofread. Flip the switch to simulate a chatty CMS.</p>
</div>
<label class="car-09__toggle" for="car09-verbose">
<input type="checkbox" id="car09-verbose">
<i aria-hidden="true"></i>
<span>Verbose CMS content</span>
</label>
</header>
<main class="car-09__grid">
<article class="car-09__tile car-09__tile--bend">
<header><b>A</b><h2>Default — the box bends</h2><code>aspect-ratio:16/9</code></header>
<p>Short copy: this tile is exactly 16:9.<span class="car-09__extra"> But the moment an editor pastes a second paragraph — like this one — the automatic content-based minimum kicks in and the box grows taller than its ratio instead of clipping or overflowing. No CSS changed; the contract simply yielded to the content, which is exactly what the spec intends for unpredictable text.</span></p>
<footer class="car-09__verdict car-09__verdict--ok">never clips · grows past 16:9 when needed</footer>
</article>
<article class="car-09__tile car-09__tile--strict">
<header><b>B</b><h2>Strict — the ratio wins</h2><code>min-height:0; overflow:auto</code></header>
<div class="car-09__scrollbox" tabindex="0">
<p>This tile waives the content floor, so it stays 16:9 no matter what.<span class="car-09__extra"> Feed it a novel and it will not budge: the extra text you're reading right now scrolls inside the fixed box instead of growing it. Dashboards, bento grids and anything pixel-budgeted use this posture — the geometry is law and the scrollbar is the pressure valve.</span></p>
</div>
<footer class="car-09__verdict car-09__verdict--warn">holds 16:9 · excess scrolls inside</footer>
</article>
<article class="car-09__tile car-09__tile--auto">
<header><b>C</b><h2>Replaced — auto 3/2</h2><code>aspect-ratio:auto 3/2</code></header>
<figure class="car-09__autofig">
<img src="https://images.unsplash.com/photo-1493246507139-91e8fad9978e?q=80&w=1200&auto=format&fit=crop" alt="Wide valley panorama — intrinsically wider than 3:2" loading="lazy">
<figcaption>Placeholder shape 3:2 → intrinsic shape on load. The fallback ratio only governs the wait.</figcaption>
</figure>
<footer class="car-09__verdict car-09__verdict--info">3:2 while loading · truth after</footer>
</article>
</main>
<section class="car-09__wall" aria-label="Testimonial wall using the default policy">
<h2>The default policy, deployed: a testimonial wall</h2>
<div class="car-09__quotes">
<blockquote><p>“We put <code>aspect-ratio:16/9</code> on every quote card and stopped auditing lengths.”<span class="car-09__extra"> The long ones grow, the short ones hold the line, and the grid keeps its rhythm either way — this sentence only exists to prove it.”</span></p><cite>— Priya N., design systems lead</cite></blockquote>
<blockquote><p>“Short quote. Perfect 16:9.”</p><cite>— Tom A., front-end engineer</cite></blockquote>
<blockquote><p>“The box is a preference the content can veto.”<span class="car-09__extra"> Toggle the switch above and watch this card and its neighbors negotiate independently — each tile only grows as much as its own words demand.”</span></p><cite>— June P., CSS instructor</cite></blockquote>
<blockquote><p>“Nothing clipped since migration.”</p><cite>— Marcus B., publisher</cite></blockquote>
</div>
</section>
<footer class="car-09__foot">Rule of thumb: let marketing tiles bend, make dashboards strict, give feed media <code>auto <ratio></code>. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section><section class="car-09" aria-label="Aspect ratio dynamic content fallback demo">
<div class="car-09__stage" id="car09-top">
<header class="car-09__bar">
<div>
<h1>The ratio is a preference, not a promise</h1>
<p>Three fallback policies for content nobody proofread. Flip the switch to simulate a chatty CMS.</p>
</div>
<label class="car-09__toggle" for="car09-verbose">
<input type="checkbox" id="car09-verbose">
<i aria-hidden="true"></i>
<span>Verbose CMS content</span>
</label>
</header>
<main class="car-09__grid">
<article class="car-09__tile car-09__tile--bend">
<header><b>A</b><h2>Default — the box bends</h2><code>aspect-ratio:16/9</code></header>
<p>Short copy: this tile is exactly 16:9.<span class="car-09__extra"> But the moment an editor pastes a second paragraph — like this one — the automatic content-based minimum kicks in and the box grows taller than its ratio instead of clipping or overflowing. No CSS changed; the contract simply yielded to the content, which is exactly what the spec intends for unpredictable text.</span></p>
<footer class="car-09__verdict car-09__verdict--ok">never clips · grows past 16:9 when needed</footer>
</article>
<article class="car-09__tile car-09__tile--strict">
<header><b>B</b><h2>Strict — the ratio wins</h2><code>min-height:0; overflow:auto</code></header>
<div class="car-09__scrollbox" tabindex="0">
<p>This tile waives the content floor, so it stays 16:9 no matter what.<span class="car-09__extra"> Feed it a novel and it will not budge: the extra text you're reading right now scrolls inside the fixed box instead of growing it. Dashboards, bento grids and anything pixel-budgeted use this posture — the geometry is law and the scrollbar is the pressure valve.</span></p>
</div>
<footer class="car-09__verdict car-09__verdict--warn">holds 16:9 · excess scrolls inside</footer>
</article>
<article class="car-09__tile car-09__tile--auto">
<header><b>C</b><h2>Replaced — auto 3/2</h2><code>aspect-ratio:auto 3/2</code></header>
<figure class="car-09__autofig">
<img src="https://images.unsplash.com/photo-1493246507139-91e8fad9978e?q=80&w=1200&auto=format&fit=crop" alt="Wide valley panorama — intrinsically wider than 3:2" loading="lazy">
<figcaption>Placeholder shape 3:2 → intrinsic shape on load. The fallback ratio only governs the wait.</figcaption>
</figure>
<footer class="car-09__verdict car-09__verdict--info">3:2 while loading · truth after</footer>
</article>
</main>
<section class="car-09__wall" aria-label="Testimonial wall using the default policy">
<h2>The default policy, deployed: a testimonial wall</h2>
<div class="car-09__quotes">
<blockquote><p>“We put <code>aspect-ratio:16/9</code> on every quote card and stopped auditing lengths.”<span class="car-09__extra"> The long ones grow, the short ones hold the line, and the grid keeps its rhythm either way — this sentence only exists to prove it.”</span></p><cite>— Priya N., design systems lead</cite></blockquote>
<blockquote><p>“Short quote. Perfect 16:9.”</p><cite>— Tom A., front-end engineer</cite></blockquote>
<blockquote><p>“The box is a preference the content can veto.”<span class="car-09__extra"> Toggle the switch above and watch this card and its neighbors negotiate independently — each tile only grows as much as its own words demand.”</span></p><cite>— June P., CSS instructor</cite></blockquote>
<blockquote><p>“Nothing clipped since migration.”</p><cite>— Marcus B., publisher</cite></blockquote>
</div>
</section>
<footer class="car-09__foot">Rule of thumb: let marketing tiles bend, make dashboards strict, give feed media <code>auto <ratio></code>. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>.car-09,
.car-09 *,
.car-09 *::before,
.car-09 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-09 {
--bg: oklch(0.975 0.008 95);
--ink: oklch(0.24 0.02 80);
--mut: oklch(0.5 0.02 80);
--line: oklch(0.88 0.015 95);
--acc: oklch(0.55 0.13 145);
--warn: oklch(0.62 0.14 70);
--info: oklch(0.56 0.13 240);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
display: block;
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: var(--bg);
}
.car-09__stage {
width: 100%;
container: car09/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-09__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
flex-wrap: wrap;
padding: 22px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
}
.car-09__bar h1 {
font-size: clamp(18px,2.8cqi,26px);
letter-spacing: -.02em;
font-weight: 800;
}
.car-09__bar p {
font-size: 13px;
color: var(--mut);
margin-top: 4px;
}
.car-09__toggle {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: 13.5px;
font-weight: 700;
min-height: 44px;
}
.car-09__toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.car-09__toggle i {
width: 46px;
height: 26px;
border-radius: 99px;
background: oklch(0.82 0.02 95);
position: relative;
transition: background .25s;
flex: none;
}
.car-09__toggle i::after {
content: "";
position: absolute;
left: 3px;
top: 3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: oklch(0.99 0 0);
box-shadow: 0 1px 4px oklch(0.3 0.02 80/.4);
transition: translate .25s cubic-bezier(.34,1.56,.64,1);
}
.car-09__toggle input:checked + i {
background: var(--acc);
}
.car-09__toggle input:checked + i::after {
translate: 20px 0;
}
.car-09__toggle input:focus-visible + i {
outline: 3px solid var(--acc);
outline-offset: 2px;
}
.car-09__extra {
display: none;
}
.car-09:has(#car09-verbose:checked) .car-09__extra {
display: inline;
}
.car-09__grid {
display: grid;
gap: clamp(14px,2.5cqi,22px);
grid-template-columns: repeat(auto-fit,minmax(min(290px,100%),1fr));
align-items: start;
padding: clamp(18px,3.5cqi,32px) clamp(16px,4cqi,44px);
}
.car-09__tile {
display: flex;
flex-direction: column;
border: 1px solid var(--line);
border-radius: 16px;
background: oklch(1 0 0);
box-shadow: 0 1px 3px oklch(0.3 0.02 80/.06);
}
.car-09__tile--bend,
.car-09__wall blockquote {
aspect-ratio: 16/9;
}
.car-09__tile--strict {
aspect-ratio: 16/9;
min-height: 0;
}
.car-09__tile header {
display: flex;
align-items: center;
gap: 9px;
padding: 13px 16px 0;
flex-wrap: wrap;
}
.car-09__tile header b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 8px;
background: var(--ink);
color: var(--bg);
font-size: 12px;
font-weight: 800;
flex: none;
}
.car-09__tile h2 {
font-size: 14.5px;
font-weight: 800;
letter-spacing: -.01em;
}
.car-09__tile header code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--mut);
margin-left: auto;
}
.car-09__tile > p,
.car-09__scrollbox p {
padding: 10px 16px 12px;
font-size: 13.5px;
line-height: 1.6;
color: var(--mut);
}
.car-09__scrollbox {
flex: 1;
min-height: 0;
overflow: auto;
scrollbar-width: thin;
}
.car-09__scrollbox:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
border-radius: 8px;
}
.car-09__autofig {
padding: 10px 16px 12px;
}
.car-09__autofig img {
width: 100%;
height: auto;
aspect-ratio: auto 3/2;
object-fit: cover;
border-radius: 10px;
background: linear-gradient(130deg,oklch(0.85 0.03 95),oklch(0.75 0.05 145));
}
.car-09__autofig figcaption {
font-size: 11.5px;
color: var(--mut);
margin-top: 8px;
line-height: 1.5;
}
.car-09__verdict {
margin-top: auto;
padding: 9px 16px;
border-top: 1px dashed var(--line);
font-family: ui-monospace,Menlo,monospace;
font-size: 10.5px;
letter-spacing: .02em;
}
.car-09__verdict--ok {
color: var(--acc);
}
.car-09__verdict--warn {
color: var(--warn);
}
.car-09__verdict--info {
color: var(--info);
}
.car-09__wall {
padding: 6px clamp(16px,4cqi,44px) 10px;
}
.car-09__wall h2 {
font-size: clamp(16px,2.4cqi,21px);
letter-spacing: -.015em;
font-weight: 800;
margin-bottom: 14px;
}
.car-09__quotes {
display: grid;
gap: 14px;
grid-template-columns: repeat(auto-fit,minmax(min(240px,100%),1fr));
align-items: start;
}
.car-09__wall blockquote {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 10px;
padding: 16px;
border: 1px solid var(--line);
border-radius: 14px;
background: linear-gradient(160deg,oklch(1 0 0),oklch(0.97 0.01 95));
}
.car-09__wall blockquote p {
font-size: 13.5px;
line-height: 1.55;
text-wrap: pretty;
}
.car-09__wall code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.93 0.015 95);
padding: 1px 5px;
border-radius: 4px;
}
.car-09__wall cite {
font-style: normal;
font-size: 11.5px;
color: var(--mut);
}
.car-09__foot {
padding: 18px clamp(16px,4cqi,44px) 32px;
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
border-top: 1px solid var(--line);
margin-top: 16px;
}
.car-09__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.015 95);
padding: 2px 6px;
border-radius: 5px;
}
@media (prefers-reduced-motion: reduce) {
.car-09 * {
transition-duration: .01ms !important;
}
}.car-09,
.car-09 *,
.car-09 *::before,
.car-09 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-09 {
--bg: oklch(0.975 0.008 95);
--ink: oklch(0.24 0.02 80);
--mut: oklch(0.5 0.02 80);
--line: oklch(0.88 0.015 95);
--acc: oklch(0.55 0.13 145);
--warn: oklch(0.62 0.14 70);
--info: oklch(0.56 0.13 240);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
display: block;
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: var(--bg);
}
.car-09__stage {
width: 100%;
container: car09/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-09__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
flex-wrap: wrap;
padding: 22px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
}
.car-09__bar h1 {
font-size: clamp(18px,2.8cqi,26px);
letter-spacing: -.02em;
font-weight: 800;
}
.car-09__bar p {
font-size: 13px;
color: var(--mut);
margin-top: 4px;
}
.car-09__toggle {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: 13.5px;
font-weight: 700;
min-height: 44px;
}
.car-09__toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.car-09__toggle i {
width: 46px;
height: 26px;
border-radius: 99px;
background: oklch(0.82 0.02 95);
position: relative;
transition: background .25s;
flex: none;
}
.car-09__toggle i::after {
content: "";
position: absolute;
left: 3px;
top: 3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: oklch(0.99 0 0);
box-shadow: 0 1px 4px oklch(0.3 0.02 80/.4);
transition: translate .25s cubic-bezier(.34,1.56,.64,1);
}
.car-09__toggle input:checked + i {
background: var(--acc);
}
.car-09__toggle input:checked + i::after {
translate: 20px 0;
}
.car-09__toggle input:focus-visible + i {
outline: 3px solid var(--acc);
outline-offset: 2px;
}
.car-09__extra {
display: none;
}
.car-09:has(#car09-verbose:checked) .car-09__extra {
display: inline;
}
.car-09__grid {
display: grid;
gap: clamp(14px,2.5cqi,22px);
grid-template-columns: repeat(auto-fit,minmax(min(290px,100%),1fr));
align-items: start;
padding: clamp(18px,3.5cqi,32px) clamp(16px,4cqi,44px);
}
.car-09__tile {
display: flex;
flex-direction: column;
border: 1px solid var(--line);
border-radius: 16px;
background: oklch(1 0 0);
box-shadow: 0 1px 3px oklch(0.3 0.02 80/.06);
}
.car-09__tile--bend,
.car-09__wall blockquote {
aspect-ratio: 16/9;
}
.car-09__tile--strict {
aspect-ratio: 16/9;
min-height: 0;
}
.car-09__tile header {
display: flex;
align-items: center;
gap: 9px;
padding: 13px 16px 0;
flex-wrap: wrap;
}
.car-09__tile header b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 8px;
background: var(--ink);
color: var(--bg);
font-size: 12px;
font-weight: 800;
flex: none;
}
.car-09__tile h2 {
font-size: 14.5px;
font-weight: 800;
letter-spacing: -.01em;
}
.car-09__tile header code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--mut);
margin-left: auto;
}
.car-09__tile > p,
.car-09__scrollbox p {
padding: 10px 16px 12px;
font-size: 13.5px;
line-height: 1.6;
color: var(--mut);
}
.car-09__scrollbox {
flex: 1;
min-height: 0;
overflow: auto;
scrollbar-width: thin;
}
.car-09__scrollbox:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
border-radius: 8px;
}
.car-09__autofig {
padding: 10px 16px 12px;
}
.car-09__autofig img {
width: 100%;
height: auto;
aspect-ratio: auto 3/2;
object-fit: cover;
border-radius: 10px;
background: linear-gradient(130deg,oklch(0.85 0.03 95),oklch(0.75 0.05 145));
}
.car-09__autofig figcaption {
font-size: 11.5px;
color: var(--mut);
margin-top: 8px;
line-height: 1.5;
}
.car-09__verdict {
margin-top: auto;
padding: 9px 16px;
border-top: 1px dashed var(--line);
font-family: ui-monospace,Menlo,monospace;
font-size: 10.5px;
letter-spacing: .02em;
}
.car-09__verdict--ok {
color: var(--acc);
}
.car-09__verdict--warn {
color: var(--warn);
}
.car-09__verdict--info {
color: var(--info);
}
.car-09__wall {
padding: 6px clamp(16px,4cqi,44px) 10px;
}
.car-09__wall h2 {
font-size: clamp(16px,2.4cqi,21px);
letter-spacing: -.015em;
font-weight: 800;
margin-bottom: 14px;
}
.car-09__quotes {
display: grid;
gap: 14px;
grid-template-columns: repeat(auto-fit,minmax(min(240px,100%),1fr));
align-items: start;
}
.car-09__wall blockquote {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 10px;
padding: 16px;
border: 1px solid var(--line);
border-radius: 14px;
background: linear-gradient(160deg,oklch(1 0 0),oklch(0.97 0.01 95));
}
.car-09__wall blockquote p {
font-size: 13.5px;
line-height: 1.55;
text-wrap: pretty;
}
.car-09__wall code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.93 0.015 95);
padding: 1px 5px;
border-radius: 4px;
}
.car-09__wall cite {
font-style: normal;
font-size: 11.5px;
color: var(--mut);
}
.car-09__foot {
padding: 18px clamp(16px,4cqi,44px) 32px;
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
border-top: 1px solid var(--line);
margin-top: 16px;
}
.car-09__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.015 95);
padding: 2px 6px;
border-radius: 5px;
}
@media (prefers-reduced-motion: reduce) {
.car-09 * {
transition-duration: .01ms !important;
}
}Here's a working CSS Aspect Ratio Demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Aspect Ratio Dynamic Content Fallback
Source: https://codefronts.com/layouts/css-aspect-ratio/css-aspect-ratio-dynamic-content-fallback/
What happens when the words don't fit the ratio? This demo makes the aspect-ratio contract legible: it's a preferred size, not a promise. Default tiles bend — content-based minimum sizing lets long CMS copy grow the box past 16:9 instead of spilling. Strict tiles (min-height: 0) hold the ratio and scroll inside. And aspect-ratio: auto 3/2 gives images a placeholder shape that yields to their intrinsic one on arrival. Flip the 'verbose CMS' switch and watch each policy respond.
## HTML
```html
<section class="car-09" aria-label="Aspect ratio dynamic content fallback demo">
<div class="car-09__stage" id="car09-top">
<header class="car-09__bar">
<div>
<h1>The ratio is a preference, not a promise</h1>
<p>Three fallback policies for content nobody proofread. Flip the switch to simulate a chatty CMS.</p>
</div>
<label class="car-09__toggle" for="car09-verbose">
<input type="checkbox" id="car09-verbose">
<i aria-hidden="true"></i>
<span>Verbose CMS content</span>
</label>
</header>
<main class="car-09__grid">
<article class="car-09__tile car-09__tile--bend">
<header><b>A</b><h2>Default — the box bends</h2><code>aspect-ratio:16/9</code></header>
<p>Short copy: this tile is exactly 16:9.<span class="car-09__extra"> But the moment an editor pastes a second paragraph — like this one — the automatic content-based minimum kicks in and the box grows taller than its ratio instead of clipping or overflowing. No CSS changed; the contract simply yielded to the content, which is exactly what the spec intends for unpredictable text.</span></p>
<footer class="car-09__verdict car-09__verdict--ok">never clips · grows past 16:9 when needed</footer>
</article>
<article class="car-09__tile car-09__tile--strict">
<header><b>B</b><h2>Strict — the ratio wins</h2><code>min-height:0; overflow:auto</code></header>
<div class="car-09__scrollbox" tabindex="0">
<p>This tile waives the content floor, so it stays 16:9 no matter what.<span class="car-09__extra"> Feed it a novel and it will not budge: the extra text you're reading right now scrolls inside the fixed box instead of growing it. Dashboards, bento grids and anything pixel-budgeted use this posture — the geometry is law and the scrollbar is the pressure valve.</span></p>
</div>
<footer class="car-09__verdict car-09__verdict--warn">holds 16:9 · excess scrolls inside</footer>
</article>
<article class="car-09__tile car-09__tile--auto">
<header><b>C</b><h2>Replaced — auto 3/2</h2><code>aspect-ratio:auto 3/2</code></header>
<figure class="car-09__autofig">
<img src="https://images.unsplash.com/photo-1493246507139-91e8fad9978e?q=80&w=1200&auto=format&fit=crop" alt="Wide valley panorama — intrinsically wider than 3:2" loading="lazy">
<figcaption>Placeholder shape 3:2 → intrinsic shape on load. The fallback ratio only governs the wait.</figcaption>
</figure>
<footer class="car-09__verdict car-09__verdict--info">3:2 while loading · truth after</footer>
</article>
</main>
<section class="car-09__wall" aria-label="Testimonial wall using the default policy">
<h2>The default policy, deployed: a testimonial wall</h2>
<div class="car-09__quotes">
<blockquote><p>“We put <code>aspect-ratio:16/9</code> on every quote card and stopped auditing lengths.”<span class="car-09__extra"> The long ones grow, the short ones hold the line, and the grid keeps its rhythm either way — this sentence only exists to prove it.”</span></p><cite>— Priya N., design systems lead</cite></blockquote>
<blockquote><p>“Short quote. Perfect 16:9.”</p><cite>— Tom A., front-end engineer</cite></blockquote>
<blockquote><p>“The box is a preference the content can veto.”<span class="car-09__extra"> Toggle the switch above and watch this card and its neighbors negotiate independently — each tile only grows as much as its own words demand.”</span></p><cite>— June P., CSS instructor</cite></blockquote>
<blockquote><p>“Nothing clipped since migration.”</p><cite>— Marcus B., publisher</cite></blockquote>
</div>
</section>
<footer class="car-09__foot">Rule of thumb: let marketing tiles bend, make dashboards strict, give feed media <code>auto <ratio></code>. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>
```
## CSS
```css
.car-09,
.car-09 *,
.car-09 *::before,
.car-09 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-09 {
--bg: oklch(0.975 0.008 95);
--ink: oklch(0.24 0.02 80);
--mut: oklch(0.5 0.02 80);
--line: oklch(0.88 0.015 95);
--acc: oklch(0.55 0.13 145);
--warn: oklch(0.62 0.14 70);
--info: oklch(0.56 0.13 240);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
display: block;
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: var(--bg);
}
.car-09__stage {
width: 100%;
container: car09/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-09__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
flex-wrap: wrap;
padding: 22px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
}
.car-09__bar h1 {
font-size: clamp(18px,2.8cqi,26px);
letter-spacing: -.02em;
font-weight: 800;
}
.car-09__bar p {
font-size: 13px;
color: var(--mut);
margin-top: 4px;
}
.car-09__toggle {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: 13.5px;
font-weight: 700;
min-height: 44px;
}
.car-09__toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.car-09__toggle i {
width: 46px;
height: 26px;
border-radius: 99px;
background: oklch(0.82 0.02 95);
position: relative;
transition: background .25s;
flex: none;
}
.car-09__toggle i::after {
content: "";
position: absolute;
left: 3px;
top: 3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: oklch(0.99 0 0);
box-shadow: 0 1px 4px oklch(0.3 0.02 80/.4);
transition: translate .25s cubic-bezier(.34,1.56,.64,1);
}
.car-09__toggle input:checked + i {
background: var(--acc);
}
.car-09__toggle input:checked + i::after {
translate: 20px 0;
}
.car-09__toggle input:focus-visible + i {
outline: 3px solid var(--acc);
outline-offset: 2px;
}
.car-09__extra {
display: none;
}
.car-09:has(#car09-verbose:checked) .car-09__extra {
display: inline;
}
.car-09__grid {
display: grid;
gap: clamp(14px,2.5cqi,22px);
grid-template-columns: repeat(auto-fit,minmax(min(290px,100%),1fr));
align-items: start;
padding: clamp(18px,3.5cqi,32px) clamp(16px,4cqi,44px);
}
.car-09__tile {
display: flex;
flex-direction: column;
border: 1px solid var(--line);
border-radius: 16px;
background: oklch(1 0 0);
box-shadow: 0 1px 3px oklch(0.3 0.02 80/.06);
}
.car-09__tile--bend,
.car-09__wall blockquote {
aspect-ratio: 16/9;
}
.car-09__tile--strict {
aspect-ratio: 16/9;
min-height: 0;
}
.car-09__tile header {
display: flex;
align-items: center;
gap: 9px;
padding: 13px 16px 0;
flex-wrap: wrap;
}
.car-09__tile header b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 8px;
background: var(--ink);
color: var(--bg);
font-size: 12px;
font-weight: 800;
flex: none;
}
.car-09__tile h2 {
font-size: 14.5px;
font-weight: 800;
letter-spacing: -.01em;
}
.car-09__tile header code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--mut);
margin-left: auto;
}
.car-09__tile > p,
.car-09__scrollbox p {
padding: 10px 16px 12px;
font-size: 13.5px;
line-height: 1.6;
color: var(--mut);
}
.car-09__scrollbox {
flex: 1;
min-height: 0;
overflow: auto;
scrollbar-width: thin;
}
.car-09__scrollbox:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
border-radius: 8px;
}
.car-09__autofig {
padding: 10px 16px 12px;
}
.car-09__autofig img {
width: 100%;
height: auto;
aspect-ratio: auto 3/2;
object-fit: cover;
border-radius: 10px;
background: linear-gradient(130deg,oklch(0.85 0.03 95),oklch(0.75 0.05 145));
}
.car-09__autofig figcaption {
font-size: 11.5px;
color: var(--mut);
margin-top: 8px;
line-height: 1.5;
}
.car-09__verdict {
margin-top: auto;
padding: 9px 16px;
border-top: 1px dashed var(--line);
font-family: ui-monospace,Menlo,monospace;
font-size: 10.5px;
letter-spacing: .02em;
}
.car-09__verdict--ok {
color: var(--acc);
}
.car-09__verdict--warn {
color: var(--warn);
}
.car-09__verdict--info {
color: var(--info);
}
.car-09__wall {
padding: 6px clamp(16px,4cqi,44px) 10px;
}
.car-09__wall h2 {
font-size: clamp(16px,2.4cqi,21px);
letter-spacing: -.015em;
font-weight: 800;
margin-bottom: 14px;
}
.car-09__quotes {
display: grid;
gap: 14px;
grid-template-columns: repeat(auto-fit,minmax(min(240px,100%),1fr));
align-items: start;
}
.car-09__wall blockquote {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 10px;
padding: 16px;
border: 1px solid var(--line);
border-radius: 14px;
background: linear-gradient(160deg,oklch(1 0 0),oklch(0.97 0.01 95));
}
.car-09__wall blockquote p {
font-size: 13.5px;
line-height: 1.55;
text-wrap: pretty;
}
.car-09__wall code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.93 0.015 95);
padding: 1px 5px;
border-radius: 4px;
}
.car-09__wall cite {
font-style: normal;
font-size: 11.5px;
color: var(--mut);
}
.car-09__foot {
padding: 18px clamp(16px,4cqi,44px) 32px;
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
border-top: 1px solid var(--line);
margin-top: 16px;
}
.car-09__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.015 95);
padding: 2px 6px;
border-radius: 5px;
}
@media (prefers-reduced-motion: reduce) {
.car-09 * {
transition-duration: .01ms !important;
}
}
```Here's a working CSS Aspect Ratio Demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Aspect Ratio Dynamic Content Fallback
Source: https://codefronts.com/layouts/css-aspect-ratio/css-aspect-ratio-dynamic-content-fallback/
What happens when the words don't fit the ratio? This demo makes the aspect-ratio contract legible: it's a preferred size, not a promise. Default tiles bend — content-based minimum sizing lets long CMS copy grow the box past 16:9 instead of spilling. Strict tiles (min-height: 0) hold the ratio and scroll inside. And aspect-ratio: auto 3/2 gives images a placeholder shape that yields to their intrinsic one on arrival. Flip the 'verbose CMS' switch and watch each policy respond.
## HTML
```html
<section class="car-09" aria-label="Aspect ratio dynamic content fallback demo">
<div class="car-09__stage" id="car09-top">
<header class="car-09__bar">
<div>
<h1>The ratio is a preference, not a promise</h1>
<p>Three fallback policies for content nobody proofread. Flip the switch to simulate a chatty CMS.</p>
</div>
<label class="car-09__toggle" for="car09-verbose">
<input type="checkbox" id="car09-verbose">
<i aria-hidden="true"></i>
<span>Verbose CMS content</span>
</label>
</header>
<main class="car-09__grid">
<article class="car-09__tile car-09__tile--bend">
<header><b>A</b><h2>Default — the box bends</h2><code>aspect-ratio:16/9</code></header>
<p>Short copy: this tile is exactly 16:9.<span class="car-09__extra"> But the moment an editor pastes a second paragraph — like this one — the automatic content-based minimum kicks in and the box grows taller than its ratio instead of clipping or overflowing. No CSS changed; the contract simply yielded to the content, which is exactly what the spec intends for unpredictable text.</span></p>
<footer class="car-09__verdict car-09__verdict--ok">never clips · grows past 16:9 when needed</footer>
</article>
<article class="car-09__tile car-09__tile--strict">
<header><b>B</b><h2>Strict — the ratio wins</h2><code>min-height:0; overflow:auto</code></header>
<div class="car-09__scrollbox" tabindex="0">
<p>This tile waives the content floor, so it stays 16:9 no matter what.<span class="car-09__extra"> Feed it a novel and it will not budge: the extra text you're reading right now scrolls inside the fixed box instead of growing it. Dashboards, bento grids and anything pixel-budgeted use this posture — the geometry is law and the scrollbar is the pressure valve.</span></p>
</div>
<footer class="car-09__verdict car-09__verdict--warn">holds 16:9 · excess scrolls inside</footer>
</article>
<article class="car-09__tile car-09__tile--auto">
<header><b>C</b><h2>Replaced — auto 3/2</h2><code>aspect-ratio:auto 3/2</code></header>
<figure class="car-09__autofig">
<img src="https://images.unsplash.com/photo-1493246507139-91e8fad9978e?q=80&w=1200&auto=format&fit=crop" alt="Wide valley panorama — intrinsically wider than 3:2" loading="lazy">
<figcaption>Placeholder shape 3:2 → intrinsic shape on load. The fallback ratio only governs the wait.</figcaption>
</figure>
<footer class="car-09__verdict car-09__verdict--info">3:2 while loading · truth after</footer>
</article>
</main>
<section class="car-09__wall" aria-label="Testimonial wall using the default policy">
<h2>The default policy, deployed: a testimonial wall</h2>
<div class="car-09__quotes">
<blockquote><p>“We put <code>aspect-ratio:16/9</code> on every quote card and stopped auditing lengths.”<span class="car-09__extra"> The long ones grow, the short ones hold the line, and the grid keeps its rhythm either way — this sentence only exists to prove it.”</span></p><cite>— Priya N., design systems lead</cite></blockquote>
<blockquote><p>“Short quote. Perfect 16:9.”</p><cite>— Tom A., front-end engineer</cite></blockquote>
<blockquote><p>“The box is a preference the content can veto.”<span class="car-09__extra"> Toggle the switch above and watch this card and its neighbors negotiate independently — each tile only grows as much as its own words demand.”</span></p><cite>— June P., CSS instructor</cite></blockquote>
<blockquote><p>“Nothing clipped since migration.”</p><cite>— Marcus B., publisher</cite></blockquote>
</div>
</section>
<footer class="car-09__foot">Rule of thumb: let marketing tiles bend, make dashboards strict, give feed media <code>auto <ratio></code>. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>
```
## CSS
```css
.car-09,
.car-09 *,
.car-09 *::before,
.car-09 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-09 {
--bg: oklch(0.975 0.008 95);
--ink: oklch(0.24 0.02 80);
--mut: oklch(0.5 0.02 80);
--line: oklch(0.88 0.015 95);
--acc: oklch(0.55 0.13 145);
--warn: oklch(0.62 0.14 70);
--info: oklch(0.56 0.13 240);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
display: block;
width: 100%;
min-height: 100vh;
min-height: 100svh;
background: var(--bg);
}
.car-09__stage {
width: 100%;
container: car09/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-09__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
flex-wrap: wrap;
padding: 22px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
}
.car-09__bar h1 {
font-size: clamp(18px,2.8cqi,26px);
letter-spacing: -.02em;
font-weight: 800;
}
.car-09__bar p {
font-size: 13px;
color: var(--mut);
margin-top: 4px;
}
.car-09__toggle {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: 13.5px;
font-weight: 700;
min-height: 44px;
}
.car-09__toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
.car-09__toggle i {
width: 46px;
height: 26px;
border-radius: 99px;
background: oklch(0.82 0.02 95);
position: relative;
transition: background .25s;
flex: none;
}
.car-09__toggle i::after {
content: "";
position: absolute;
left: 3px;
top: 3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: oklch(0.99 0 0);
box-shadow: 0 1px 4px oklch(0.3 0.02 80/.4);
transition: translate .25s cubic-bezier(.34,1.56,.64,1);
}
.car-09__toggle input:checked + i {
background: var(--acc);
}
.car-09__toggle input:checked + i::after {
translate: 20px 0;
}
.car-09__toggle input:focus-visible + i {
outline: 3px solid var(--acc);
outline-offset: 2px;
}
.car-09__extra {
display: none;
}
.car-09:has(#car09-verbose:checked) .car-09__extra {
display: inline;
}
.car-09__grid {
display: grid;
gap: clamp(14px,2.5cqi,22px);
grid-template-columns: repeat(auto-fit,minmax(min(290px,100%),1fr));
align-items: start;
padding: clamp(18px,3.5cqi,32px) clamp(16px,4cqi,44px);
}
.car-09__tile {
display: flex;
flex-direction: column;
border: 1px solid var(--line);
border-radius: 16px;
background: oklch(1 0 0);
box-shadow: 0 1px 3px oklch(0.3 0.02 80/.06);
}
.car-09__tile--bend,
.car-09__wall blockquote {
aspect-ratio: 16/9;
}
.car-09__tile--strict {
aspect-ratio: 16/9;
min-height: 0;
}
.car-09__tile header {
display: flex;
align-items: center;
gap: 9px;
padding: 13px 16px 0;
flex-wrap: wrap;
}
.car-09__tile header b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 8px;
background: var(--ink);
color: var(--bg);
font-size: 12px;
font-weight: 800;
flex: none;
}
.car-09__tile h2 {
font-size: 14.5px;
font-weight: 800;
letter-spacing: -.01em;
}
.car-09__tile header code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--mut);
margin-left: auto;
}
.car-09__tile > p,
.car-09__scrollbox p {
padding: 10px 16px 12px;
font-size: 13.5px;
line-height: 1.6;
color: var(--mut);
}
.car-09__scrollbox {
flex: 1;
min-height: 0;
overflow: auto;
scrollbar-width: thin;
}
.car-09__scrollbox:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
border-radius: 8px;
}
.car-09__autofig {
padding: 10px 16px 12px;
}
.car-09__autofig img {
width: 100%;
height: auto;
aspect-ratio: auto 3/2;
object-fit: cover;
border-radius: 10px;
background: linear-gradient(130deg,oklch(0.85 0.03 95),oklch(0.75 0.05 145));
}
.car-09__autofig figcaption {
font-size: 11.5px;
color: var(--mut);
margin-top: 8px;
line-height: 1.5;
}
.car-09__verdict {
margin-top: auto;
padding: 9px 16px;
border-top: 1px dashed var(--line);
font-family: ui-monospace,Menlo,monospace;
font-size: 10.5px;
letter-spacing: .02em;
}
.car-09__verdict--ok {
color: var(--acc);
}
.car-09__verdict--warn {
color: var(--warn);
}
.car-09__verdict--info {
color: var(--info);
}
.car-09__wall {
padding: 6px clamp(16px,4cqi,44px) 10px;
}
.car-09__wall h2 {
font-size: clamp(16px,2.4cqi,21px);
letter-spacing: -.015em;
font-weight: 800;
margin-bottom: 14px;
}
.car-09__quotes {
display: grid;
gap: 14px;
grid-template-columns: repeat(auto-fit,minmax(min(240px,100%),1fr));
align-items: start;
}
.car-09__wall blockquote {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 10px;
padding: 16px;
border: 1px solid var(--line);
border-radius: 14px;
background: linear-gradient(160deg,oklch(1 0 0),oklch(0.97 0.01 95));
}
.car-09__wall blockquote p {
font-size: 13.5px;
line-height: 1.55;
text-wrap: pretty;
}
.car-09__wall code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.93 0.015 95);
padding: 1px 5px;
border-radius: 4px;
}
.car-09__wall cite {
font-style: normal;
font-size: 11.5px;
color: var(--mut);
}
.car-09__foot {
padding: 18px clamp(16px,4cqi,44px) 32px;
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
border-top: 1px solid var(--line);
margin-top: 16px;
}
.car-09__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.015 95);
padding: 2px 6px;
border-radius: 5px;
}
@media (prefers-reduced-motion: reduce) {
.car-09 * {
transition-duration: .01ms !important;
}
}
```How this works
Three policies, one property. The spec's two crucial behaviors — the auto keyword and the automatic content floor — are what separate developers who fight aspect-ratio from those who deploy it on dynamic content:
.tile { aspect-ratio:16 / 9; } /* bends: content may grow it taller */
.strict{ aspect-ratio:16 / 9;
min-height:0; /* waive the content floor */
overflow:auto; } /* ratio wins; text scrolls inside */
img.card{ aspect-ratio:auto 3 / 2; }/* 3:2 while loading,
intrinsic ratio once loaded */Policy one is the default and the spec's kindest decision: boxes with a preferred aspect ratio get an automatic content-based minimum size. A 16:9 tile holding two sentences is 16:9; the same tile holding a paragraph quietly grows taller rather than overflowing. Nothing clips, nothing escapes — the ratio is treated as a design preference that real content may override. That's why you can put aspect-ratio on CMS-fed cards without auditing every entry ever written.
Policy two opts out: min-height:0 waives the floor, so the ratio becomes law and overflow:auto gives the excess text a scrollbar inside the box (dashboards and strict grids want this). Policy three is for replaced elements: aspect-ratio: auto 3/2 means 'use the intrinsic ratio when there is one; use 3:2 until there is one' — the loading placeholder that respects the image's true shape on arrival, trading a possible one-time adjustment for never lying about proportions. Demo 08 reserves a shape you enforce with cropping; this reserves a shape you surrender when the truth arrives. Both are legitimate — the difference is whether object-fit crops afterward.
Make it yours
- Pick your posture per slot: marketing tiles usually bend (default), data-dense dashboards go strict, media in feeds uses
auto <ratio>. All three coexist in one grid here. - Soften the strict policy:
overflow:clip+ a mask-image fade tells users 'there's more' without a scrollbar; pair with a 'read more' link outside the box. - Guardrail combo:
aspect-ratio:16/9; max-height:340pxkeeps bent boxes from growing absurd on 3-line-title-plus-essay entries — min/max always outrank the ratio (demo 02's lesson, reversed). - Tune the fallback ratio to your median asset: if 80% of uploads are 4:3,
auto 4/3makes the post-load adjustment invisible for most content.
Gotchas — read before shipping
- 'aspect-ratio isn't working' on text boxes is usually the content floor doing its job — the box grew because the words needed it. That's the feature; opt out with min-height:0, don't fight it with !important.
- min-height:0 without an overflow plan means text escapes the box and paints over siblings. Waiving the floor transfers responsibility for the excess to you.
- aspect-ratio:auto 3/2 still shifts layout when intrinsic ≠ 3/2 — it shrinks the lie, not the physics. For zero-shift feeds, crop to a fixed ratio instead (demo 08).
- In flex/grid, stretch alignment can hand the box a definite cross size, silently disabling the ratio — align-items:start (used here) or align-self keeps the ratio in control.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by :has(), oklch(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 111+.
aspect-ratio (including the auto <ratio> form and content-based minimums) is 2021-universal across engines. The verbose-content switch uses :has(), Chrome 105 / Safari 15.4 / Firefox 121. Floor reflects oklch()/color-mix() tokens.