15 CSS Aspect Ratio Demos10 / 15
CSS Aspect Ratio Ad Banner Container
Publisher-grade ad slots that reserve their exact space before a single ad byte arrives: aspect-ratio: 728/90 for the leaderboard, 300/250 for the rectangle, 300/600 for the half-page — the raw IAB dimensions written straight into CSS, no decimal maths. Each slot shimmers as a labeled placeholder, the 'ad' arrives on a CSS delay to prove the page doesn't flinch, and a container query swaps the leaderboard for a 320/50 mobile banner when the column gets narrow. Ads pay the bills; this is how they stop costing you CLS.
Published
The code
<section class="car-10" aria-label="Ad banner container demo">
<div class="car-10__stage" id="car10-top">
<header class="car-10__bar">
<a class="car-10__brand" href="#car10-top">The Morning Brief</a>
<nav class="car-10__nav" aria-label="Sections"><a href="#car10-top">Media</a><a href="#car10-top">Adtech</a><a href="#car10-top">Metrics</a></nav>
<a class="car-10__sub" href="#car10-top">Subscribe</a>
</header>
<div class="car-10__slotzone">
<p class="car-10__adlabel">Advertisement · leaderboard 728×90 (320×50 when narrow)</p>
<div class="car-10__slot car-10__slot--leader">
<a class="car-10__ad car-10__ad--leader" href="#car10-top" aria-label="House ad: Fjell boots">
<b>FJELL</b><span>Boots that outlast the trail. Guaranteed for a decade.</span><em>Shop now →</em>
</a>
</div>
</div>
<main class="car-10__main">
<article class="car-10__article">
<p class="car-10__kicker">Adtech · CLS</p>
<h1>The cheapest ranking win in publishing is an empty box</h1>
<p class="car-10__meta">By Harriet Cole · August 3, 2026</p>
<p>Every slot on this page was full-size before the auction returned. The leaderboard above, the rectangle below, the half-page in the sidebar — each is an <code>aspect-ratio</code> reservation wearing a skeleton, which is why the paragraph you are reading has not moved since first paint.</p>
<p>Watch the creatives arrive (they're on a deliberate 1.4–2.2s delay). The boxes don't grow, the article doesn't lurch, and the CLS report stays at zero — the exact failure mode that used to cost publishers a Core Web Vitals grade every time a bid resolved late.</p>
<div class="car-10__slotzone car-10__slotzone--inline">
<p class="car-10__adlabel">Advertisement · medium rectangle 300×250</p>
<div class="car-10__slot car-10__slot--mrec">
<a class="car-10__ad car-10__ad--mrec" href="#car10-top" aria-label="House ad: Mono focus app" style="--img:url('https://images.unsplash.com/photo-1553062407-98eeb64c6a62?q=80&w=600&h=500&auto=format&fit=crop')">
<i aria-hidden="true"></i><b>Mono</b><span>One task at a time. The focus app for deadline weeks.</span><em>Try free →</em>
</a>
</div>
</div>
<p>The trick bears repeating because it's so unglamorous: write the IAB size into the ratio — <code>aspect-ratio: 728/90</code>, <code>300/250</code>, <code>300/600</code> — cap it with <code>max-width</code>, and let the box scale proportionally in narrow columns. When the column can't honor a leaderboard at all, a container query swaps the slot for the 320×50 mobile unit. The column is the breakpoint, not the screen.</p>
<p>Unfilled inventory keeps the box too. A reserved slot that stays a quiet skeleton costs a few hundred square pixels; a collapsing slot costs a layout shift on every page where the auction passes. Publishers who measured both stopped collapsing years ago.</p>
</article>
<aside class="car-10__side" aria-label="Sidebar">
<p class="car-10__adlabel">Advertisement · half page 300×600</p>
<div class="car-10__slot car-10__slot--half">
<a class="car-10__ad car-10__ad--half" href="#car10-top" aria-label="House ad: Meridian data">
<b>Meridian Data</b><span>Your dashboards, minus the 40 tabs. Warehouse-native analytics for newsrooms.</span><i aria-hidden="true"></i><em>Book a demo →</em>
</a>
</div>
<div class="car-10__widget">
<h2>Most read</h2>
<ol><li><a href="#car10-top">Ratio maths for ad ops: the one-page cheat sheet</a></li><li><a href="#car10-top">Why the 320×50 still rules mobile</a></li><li><a href="#car10-top">Skeletons that convert better than spinners</a></li></ol>
</div>
</aside>
</main>
<footer class="car-10__foot">Slots reserve with <code>aspect-ratio</code> + <code>max-width</code>; creatives arrive whenever they like. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section><section class="car-10" aria-label="Ad banner container demo">
<div class="car-10__stage" id="car10-top">
<header class="car-10__bar">
<a class="car-10__brand" href="#car10-top">The Morning Brief</a>
<nav class="car-10__nav" aria-label="Sections"><a href="#car10-top">Media</a><a href="#car10-top">Adtech</a><a href="#car10-top">Metrics</a></nav>
<a class="car-10__sub" href="#car10-top">Subscribe</a>
</header>
<div class="car-10__slotzone">
<p class="car-10__adlabel">Advertisement · leaderboard 728×90 (320×50 when narrow)</p>
<div class="car-10__slot car-10__slot--leader">
<a class="car-10__ad car-10__ad--leader" href="#car10-top" aria-label="House ad: Fjell boots">
<b>FJELL</b><span>Boots that outlast the trail. Guaranteed for a decade.</span><em>Shop now →</em>
</a>
</div>
</div>
<main class="car-10__main">
<article class="car-10__article">
<p class="car-10__kicker">Adtech · CLS</p>
<h1>The cheapest ranking win in publishing is an empty box</h1>
<p class="car-10__meta">By Harriet Cole · August 3, 2026</p>
<p>Every slot on this page was full-size before the auction returned. The leaderboard above, the rectangle below, the half-page in the sidebar — each is an <code>aspect-ratio</code> reservation wearing a skeleton, which is why the paragraph you are reading has not moved since first paint.</p>
<p>Watch the creatives arrive (they're on a deliberate 1.4–2.2s delay). The boxes don't grow, the article doesn't lurch, and the CLS report stays at zero — the exact failure mode that used to cost publishers a Core Web Vitals grade every time a bid resolved late.</p>
<div class="car-10__slotzone car-10__slotzone--inline">
<p class="car-10__adlabel">Advertisement · medium rectangle 300×250</p>
<div class="car-10__slot car-10__slot--mrec">
<a class="car-10__ad car-10__ad--mrec" href="#car10-top" aria-label="House ad: Mono focus app" style="--img:url('https://images.unsplash.com/photo-1553062407-98eeb64c6a62?q=80&w=600&h=500&auto=format&fit=crop')">
<i aria-hidden="true"></i><b>Mono</b><span>One task at a time. The focus app for deadline weeks.</span><em>Try free →</em>
</a>
</div>
</div>
<p>The trick bears repeating because it's so unglamorous: write the IAB size into the ratio — <code>aspect-ratio: 728/90</code>, <code>300/250</code>, <code>300/600</code> — cap it with <code>max-width</code>, and let the box scale proportionally in narrow columns. When the column can't honor a leaderboard at all, a container query swaps the slot for the 320×50 mobile unit. The column is the breakpoint, not the screen.</p>
<p>Unfilled inventory keeps the box too. A reserved slot that stays a quiet skeleton costs a few hundred square pixels; a collapsing slot costs a layout shift on every page where the auction passes. Publishers who measured both stopped collapsing years ago.</p>
</article>
<aside class="car-10__side" aria-label="Sidebar">
<p class="car-10__adlabel">Advertisement · half page 300×600</p>
<div class="car-10__slot car-10__slot--half">
<a class="car-10__ad car-10__ad--half" href="#car10-top" aria-label="House ad: Meridian data">
<b>Meridian Data</b><span>Your dashboards, minus the 40 tabs. Warehouse-native analytics for newsrooms.</span><i aria-hidden="true"></i><em>Book a demo →</em>
</a>
</div>
<div class="car-10__widget">
<h2>Most read</h2>
<ol><li><a href="#car10-top">Ratio maths for ad ops: the one-page cheat sheet</a></li><li><a href="#car10-top">Why the 320×50 still rules mobile</a></li><li><a href="#car10-top">Skeletons that convert better than spinners</a></li></ol>
</div>
</aside>
</main>
<footer class="car-10__foot">Slots reserve with <code>aspect-ratio</code> + <code>max-width</code>; creatives arrive whenever they like. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>.car-10,
.car-10 *,
.car-10 *::before,
.car-10 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-10 {
--bg: oklch(0.97 0.004 250);
--ink: oklch(0.22 0.015 260);
--mut: oklch(0.5 0.012 260);
--line: oklch(0.89 0.008 255);
--acc: oklch(0.55 0.17 255);
--skeleton: oklch(0.93 0.006 255);
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-10__stage {
width: 100%;
container: car10/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-10__bar {
display: flex;
align-items: center;
gap: 18px;
padding: 14px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
background: oklch(1 0 0);
}
.car-10__brand {
font-size: 17px;
font-weight: 800;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
}
.car-10__nav {
display: flex;
gap: 2px;
margin-inline: auto;
}
.car-10__nav a {
display: grid;
place-items: center;
min-height: 44px;
padding: 0 12px;
border-radius: 9px;
font-size: 13px;
font-weight: 600;
color: var(--mut);
text-decoration: none;
transition: color .2s,background .2s;
}
.car-10__nav a:hover,
.car-10__nav a:focus-visible {
color: var(--ink);
background: oklch(0.94 0.006 255);
}
.car-10__nav a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
}
.car-10__sub {
display: grid;
place-items: center;
min-height: 40px;
padding: 0 16px;
border-radius: 99px;
background: var(--ink);
color: oklch(0.98 0 0);
font-size: 12.5px;
font-weight: 700;
text-decoration: none;
transition: background .2s;
}
.car-10__sub:hover,
.car-10__sub:focus-visible {
background: var(--acc);
}
.car-10__sub:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.car-10__slotzone {
padding: 16px clamp(16px,4cqi,44px) 4px;
text-align: center;
}
.car-10__slotzone--inline {
padding: 18px 0 6px;
}
.car-10__adlabel {
font-size: 9.5px;
font-weight: 700;
letter-spacing: .14em;
text-transform: uppercase;
color: oklch(0.62 0.01 260);
margin-bottom: 6px;
}
.car-10__slot {
position: relative;
margin-inline: auto;
border: 1px dashed oklch(0.82 0.01 255);
border-radius: 8px;
overflow: hidden;
background: linear-gradient(110deg,var(--skeleton) 30%,oklch(0.96 0.004 255) 45%,var(--skeleton) 60%) 0 0/200% 100%;
animation: car10-shimmer 1.6s linear infinite;
}
@keyframes car10-shimmer {
to {
background-position: -200% 0;
}
}
.car-10__slot--leader {
aspect-ratio: 728/90;
max-width: 728px;
}
.car-10__slot--mrec {
aspect-ratio: 300/250;
max-width: 300px;
}
.car-10__slot--half {
aspect-ratio: 300/600;
max-width: 300px;
}
.car-10__ad {
position: absolute;
inset: 0;
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
text-decoration: none;
color: oklch(0.98 0 0);
opacity: 0;
animation: car10-arrive .5s ease 1.4s both;
}
@keyframes car10-arrive {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.car-10__ad--leader {
background: linear-gradient(100deg,oklch(0.35 0.08 150),oklch(0.5 0.11 130));
justify-content: center;
text-align: left;
}
.car-10__ad--leader b {
font-size: clamp(14px,2.4cqi,19px);
letter-spacing: .22em;
}
.car-10__ad--leader span {
font-size: clamp(10px,1.8cqi,13px);
opacity: .92;
max-width: 46ch;
}
.car-10__ad--leader em {
font-style: normal;
font-size: clamp(10px,1.7cqi,12.5px);
font-weight: 700;
padding: 7px 12px;
border-radius: 99px;
background: oklch(0.98 0 0/.16);
border: 1px solid oklch(0.98 0 0/.4);
white-space: nowrap;
}
.car-10__ad--mrec {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
gap: 4px;
padding: 14px;
background: oklch(0.3 0.05 280);
animation-delay: 2s;
}
.car-10__ad--mrec i {
position: absolute;
inset: 0;
background: linear-gradient(oklch(0.2 0.04 280/.15),oklch(0.14 0.04 280/.85)),var(--img);
background-size: cover;
background-position: center;
z-index: -1;
margin: 0;
}
.car-10__ad--mrec b {
font-size: 17px;
letter-spacing: -.01em;
}
.car-10__ad--mrec span {
font-size: 11.5px;
line-height: 1.45;
opacity: .92;
}
.car-10__ad--mrec em {
font-style: normal;
font-size: 11.5px;
font-weight: 700;
margin-top: 6px;
padding: 8px 12px;
border-radius: 8px;
background: oklch(0.98 0 0);
color: oklch(0.3 0.05 280);
}
.car-10__ad--half {
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 8px;
padding: 22px;
background: linear-gradient(170deg,oklch(0.28 0.06 255),oklch(0.42 0.12 285));
animation-delay: 2.2s;
}
.car-10__ad--half b {
font-size: 19px;
letter-spacing: -.01em;
}
.car-10__ad--half span {
font-size: 12.5px;
line-height: 1.55;
opacity: .92;
}
.car-10__ad--half i {
width: 100%;
aspect-ratio: 1;
border-radius: 12px;
margin: 8px 0;
background: radial-gradient(60% 60% at 35% 30%,oklch(0.85 0.1 285/.5),transparent 70%),conic-gradient(from 200deg,oklch(0.5 0.14 285),oklch(0.65 0.16 255),oklch(0.5 0.14 285));
border: 1px solid oklch(0.98 0 0/.25);
}
.car-10__ad--half em {
font-style: normal;
font-size: 12px;
font-weight: 700;
padding: 9px 14px;
border-radius: 9px;
background: oklch(0.98 0 0);
color: oklch(0.32 0.08 270);
}
.car-10__ad:hover em,
.car-10__ad:focus-visible em {
translate: 2px 0;
}
.car-10__ad em {
transition: translate .2s;
}
.car-10__ad:focus-visible {
outline: 3px solid var(--acc);
outline-offset: -3px;
}
.car-10__main {
display: grid;
grid-template-columns: minmax(0,1fr) 332px;
gap: clamp(20px,3.5cqi,40px);
max-width: 1120px;
margin-inline: auto;
padding: clamp(18px,3cqi,32px) clamp(16px,4cqi,44px);
align-items: start;
}
.car-10__kicker {
font-size: 11px;
font-weight: 700;
letter-spacing: .15em;
text-transform: uppercase;
color: var(--acc);
}
.car-10__article h1 {
font-size: clamp(24px,3.6cqi,36px);
line-height: 1.12;
letter-spacing: -.025em;
font-weight: 800;
margin-top: 8px;
text-wrap: balance;
}
.car-10__meta {
font-size: 12.5px;
color: var(--mut);
margin: 8px 0 4px;
}
.car-10__article > p {
font-size: 15px;
line-height: 1.7;
margin-top: 16px;
max-width: 66ch;
}
.car-10__article code,
.car-10__foot code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .88em;
background: oklch(0.92 0.008 255);
padding: 2px 6px;
border-radius: 5px;
color: oklch(0.42 0.12 255);
}
.car-10__side {
display: flex;
flex-direction: column;
gap: 18px;
text-align: center;
}
.car-10__widget {
text-align: left;
border: 1px solid var(--line);
border-radius: 14px;
padding: 16px;
background: oklch(1 0 0);
}
.car-10__widget h2 {
font-size: 12px;
font-weight: 800;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
}
.car-10__widget ol {
list-style: none;
counter-reset: mr;
}
.car-10__widget li {
counter-increment: mr;
display: flex;
gap: 10px;
padding: 9px 0;
border-top: 1px solid var(--line);
}
.car-10__widget li::before {
content: counter(mr,decimal-leading-zero);
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
color: var(--acc);
padding-top: 2px;
}
.car-10__widget a {
font-size: 13px;
font-weight: 600;
line-height: 1.4;
color: inherit;
text-decoration: none;
}
.car-10__widget a:hover,
.car-10__widget a:focus-visible {
color: var(--acc);
text-decoration: underline;
text-underline-offset: 3px;
}
.car-10__widget a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
border-radius: 2px;
}
.car-10__foot {
max-width: 1120px;
margin-inline: auto;
padding: 16px clamp(16px,4cqi,44px) 32px;
border-top: 1px solid var(--line);
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
}
@container car10 (width < 560px) {
.car-10__slot--leader {
aspect-ratio: 320/50;
max-width: 320px;
}
.car-10__ad--leader span {
display: none;
}
}
@container car10 (width < 880px) {
.car-10__main {
grid-template-columns: 1fr;
}
.car-10__nav {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.car-10__slot {
animation: none;
}
.car-10__ad {
animation-duration: .01ms;
animation-delay: .5s;
}
.car-10 * {
transition-duration: .01ms !important;
}
}.car-10,
.car-10 *,
.car-10 *::before,
.car-10 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-10 {
--bg: oklch(0.97 0.004 250);
--ink: oklch(0.22 0.015 260);
--mut: oklch(0.5 0.012 260);
--line: oklch(0.89 0.008 255);
--acc: oklch(0.55 0.17 255);
--skeleton: oklch(0.93 0.006 255);
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-10__stage {
width: 100%;
container: car10/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-10__bar {
display: flex;
align-items: center;
gap: 18px;
padding: 14px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
background: oklch(1 0 0);
}
.car-10__brand {
font-size: 17px;
font-weight: 800;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
}
.car-10__nav {
display: flex;
gap: 2px;
margin-inline: auto;
}
.car-10__nav a {
display: grid;
place-items: center;
min-height: 44px;
padding: 0 12px;
border-radius: 9px;
font-size: 13px;
font-weight: 600;
color: var(--mut);
text-decoration: none;
transition: color .2s,background .2s;
}
.car-10__nav a:hover,
.car-10__nav a:focus-visible {
color: var(--ink);
background: oklch(0.94 0.006 255);
}
.car-10__nav a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
}
.car-10__sub {
display: grid;
place-items: center;
min-height: 40px;
padding: 0 16px;
border-radius: 99px;
background: var(--ink);
color: oklch(0.98 0 0);
font-size: 12.5px;
font-weight: 700;
text-decoration: none;
transition: background .2s;
}
.car-10__sub:hover,
.car-10__sub:focus-visible {
background: var(--acc);
}
.car-10__sub:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.car-10__slotzone {
padding: 16px clamp(16px,4cqi,44px) 4px;
text-align: center;
}
.car-10__slotzone--inline {
padding: 18px 0 6px;
}
.car-10__adlabel {
font-size: 9.5px;
font-weight: 700;
letter-spacing: .14em;
text-transform: uppercase;
color: oklch(0.62 0.01 260);
margin-bottom: 6px;
}
.car-10__slot {
position: relative;
margin-inline: auto;
border: 1px dashed oklch(0.82 0.01 255);
border-radius: 8px;
overflow: hidden;
background: linear-gradient(110deg,var(--skeleton) 30%,oklch(0.96 0.004 255) 45%,var(--skeleton) 60%) 0 0/200% 100%;
animation: car10-shimmer 1.6s linear infinite;
}
@keyframes car10-shimmer {
to {
background-position: -200% 0;
}
}
.car-10__slot--leader {
aspect-ratio: 728/90;
max-width: 728px;
}
.car-10__slot--mrec {
aspect-ratio: 300/250;
max-width: 300px;
}
.car-10__slot--half {
aspect-ratio: 300/600;
max-width: 300px;
}
.car-10__ad {
position: absolute;
inset: 0;
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
text-decoration: none;
color: oklch(0.98 0 0);
opacity: 0;
animation: car10-arrive .5s ease 1.4s both;
}
@keyframes car10-arrive {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.car-10__ad--leader {
background: linear-gradient(100deg,oklch(0.35 0.08 150),oklch(0.5 0.11 130));
justify-content: center;
text-align: left;
}
.car-10__ad--leader b {
font-size: clamp(14px,2.4cqi,19px);
letter-spacing: .22em;
}
.car-10__ad--leader span {
font-size: clamp(10px,1.8cqi,13px);
opacity: .92;
max-width: 46ch;
}
.car-10__ad--leader em {
font-style: normal;
font-size: clamp(10px,1.7cqi,12.5px);
font-weight: 700;
padding: 7px 12px;
border-radius: 99px;
background: oklch(0.98 0 0/.16);
border: 1px solid oklch(0.98 0 0/.4);
white-space: nowrap;
}
.car-10__ad--mrec {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
gap: 4px;
padding: 14px;
background: oklch(0.3 0.05 280);
animation-delay: 2s;
}
.car-10__ad--mrec i {
position: absolute;
inset: 0;
background: linear-gradient(oklch(0.2 0.04 280/.15),oklch(0.14 0.04 280/.85)),var(--img);
background-size: cover;
background-position: center;
z-index: -1;
margin: 0;
}
.car-10__ad--mrec b {
font-size: 17px;
letter-spacing: -.01em;
}
.car-10__ad--mrec span {
font-size: 11.5px;
line-height: 1.45;
opacity: .92;
}
.car-10__ad--mrec em {
font-style: normal;
font-size: 11.5px;
font-weight: 700;
margin-top: 6px;
padding: 8px 12px;
border-radius: 8px;
background: oklch(0.98 0 0);
color: oklch(0.3 0.05 280);
}
.car-10__ad--half {
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 8px;
padding: 22px;
background: linear-gradient(170deg,oklch(0.28 0.06 255),oklch(0.42 0.12 285));
animation-delay: 2.2s;
}
.car-10__ad--half b {
font-size: 19px;
letter-spacing: -.01em;
}
.car-10__ad--half span {
font-size: 12.5px;
line-height: 1.55;
opacity: .92;
}
.car-10__ad--half i {
width: 100%;
aspect-ratio: 1;
border-radius: 12px;
margin: 8px 0;
background: radial-gradient(60% 60% at 35% 30%,oklch(0.85 0.1 285/.5),transparent 70%),conic-gradient(from 200deg,oklch(0.5 0.14 285),oklch(0.65 0.16 255),oklch(0.5 0.14 285));
border: 1px solid oklch(0.98 0 0/.25);
}
.car-10__ad--half em {
font-style: normal;
font-size: 12px;
font-weight: 700;
padding: 9px 14px;
border-radius: 9px;
background: oklch(0.98 0 0);
color: oklch(0.32 0.08 270);
}
.car-10__ad:hover em,
.car-10__ad:focus-visible em {
translate: 2px 0;
}
.car-10__ad em {
transition: translate .2s;
}
.car-10__ad:focus-visible {
outline: 3px solid var(--acc);
outline-offset: -3px;
}
.car-10__main {
display: grid;
grid-template-columns: minmax(0,1fr) 332px;
gap: clamp(20px,3.5cqi,40px);
max-width: 1120px;
margin-inline: auto;
padding: clamp(18px,3cqi,32px) clamp(16px,4cqi,44px);
align-items: start;
}
.car-10__kicker {
font-size: 11px;
font-weight: 700;
letter-spacing: .15em;
text-transform: uppercase;
color: var(--acc);
}
.car-10__article h1 {
font-size: clamp(24px,3.6cqi,36px);
line-height: 1.12;
letter-spacing: -.025em;
font-weight: 800;
margin-top: 8px;
text-wrap: balance;
}
.car-10__meta {
font-size: 12.5px;
color: var(--mut);
margin: 8px 0 4px;
}
.car-10__article > p {
font-size: 15px;
line-height: 1.7;
margin-top: 16px;
max-width: 66ch;
}
.car-10__article code,
.car-10__foot code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .88em;
background: oklch(0.92 0.008 255);
padding: 2px 6px;
border-radius: 5px;
color: oklch(0.42 0.12 255);
}
.car-10__side {
display: flex;
flex-direction: column;
gap: 18px;
text-align: center;
}
.car-10__widget {
text-align: left;
border: 1px solid var(--line);
border-radius: 14px;
padding: 16px;
background: oklch(1 0 0);
}
.car-10__widget h2 {
font-size: 12px;
font-weight: 800;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
}
.car-10__widget ol {
list-style: none;
counter-reset: mr;
}
.car-10__widget li {
counter-increment: mr;
display: flex;
gap: 10px;
padding: 9px 0;
border-top: 1px solid var(--line);
}
.car-10__widget li::before {
content: counter(mr,decimal-leading-zero);
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
color: var(--acc);
padding-top: 2px;
}
.car-10__widget a {
font-size: 13px;
font-weight: 600;
line-height: 1.4;
color: inherit;
text-decoration: none;
}
.car-10__widget a:hover,
.car-10__widget a:focus-visible {
color: var(--acc);
text-decoration: underline;
text-underline-offset: 3px;
}
.car-10__widget a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
border-radius: 2px;
}
.car-10__foot {
max-width: 1120px;
margin-inline: auto;
padding: 16px clamp(16px,4cqi,44px) 32px;
border-top: 1px solid var(--line);
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
}
@container car10 (width < 560px) {
.car-10__slot--leader {
aspect-ratio: 320/50;
max-width: 320px;
}
.car-10__ad--leader span {
display: none;
}
}
@container car10 (width < 880px) {
.car-10__main {
grid-template-columns: 1fr;
}
.car-10__nav {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.car-10__slot {
animation: none;
}
.car-10__ad {
animation-duration: .01ms;
animation-delay: .5s;
}
.car-10 * {
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 Ad Banner Container
Source: https://codefronts.com/layouts/css-aspect-ratio/css-aspect-ratio-ad-banner-container/
Publisher-grade ad slots that reserve their exact space before a single ad byte arrives: aspect-ratio: 728/90 for the leaderboard, 300/250 for the rectangle, 300/600 for the half-page — the raw IAB dimensions written straight into CSS, no decimal maths. Each slot shimmers as a labeled placeholder, the 'ad' arrives on a CSS delay to prove the page doesn't flinch, and a container query swaps the leaderboard for a 320/50 mobile banner when the column gets narrow. Ads pay the bills; this is how they stop costing you CLS.
## HTML
```html
<section class="car-10" aria-label="Ad banner container demo">
<div class="car-10__stage" id="car10-top">
<header class="car-10__bar">
<a class="car-10__brand" href="#car10-top">The Morning Brief</a>
<nav class="car-10__nav" aria-label="Sections"><a href="#car10-top">Media</a><a href="#car10-top">Adtech</a><a href="#car10-top">Metrics</a></nav>
<a class="car-10__sub" href="#car10-top">Subscribe</a>
</header>
<div class="car-10__slotzone">
<p class="car-10__adlabel">Advertisement · leaderboard 728×90 (320×50 when narrow)</p>
<div class="car-10__slot car-10__slot--leader">
<a class="car-10__ad car-10__ad--leader" href="#car10-top" aria-label="House ad: Fjell boots">
<b>FJELL</b><span>Boots that outlast the trail. Guaranteed for a decade.</span><em>Shop now →</em>
</a>
</div>
</div>
<main class="car-10__main">
<article class="car-10__article">
<p class="car-10__kicker">Adtech · CLS</p>
<h1>The cheapest ranking win in publishing is an empty box</h1>
<p class="car-10__meta">By Harriet Cole · August 3, 2026</p>
<p>Every slot on this page was full-size before the auction returned. The leaderboard above, the rectangle below, the half-page in the sidebar — each is an <code>aspect-ratio</code> reservation wearing a skeleton, which is why the paragraph you are reading has not moved since first paint.</p>
<p>Watch the creatives arrive (they're on a deliberate 1.4–2.2s delay). The boxes don't grow, the article doesn't lurch, and the CLS report stays at zero — the exact failure mode that used to cost publishers a Core Web Vitals grade every time a bid resolved late.</p>
<div class="car-10__slotzone car-10__slotzone--inline">
<p class="car-10__adlabel">Advertisement · medium rectangle 300×250</p>
<div class="car-10__slot car-10__slot--mrec">
<a class="car-10__ad car-10__ad--mrec" href="#car10-top" aria-label="House ad: Mono focus app" style="--img:url('https://images.unsplash.com/photo-1553062407-98eeb64c6a62?q=80&w=600&h=500&auto=format&fit=crop')">
<i aria-hidden="true"></i><b>Mono</b><span>One task at a time. The focus app for deadline weeks.</span><em>Try free →</em>
</a>
</div>
</div>
<p>The trick bears repeating because it's so unglamorous: write the IAB size into the ratio — <code>aspect-ratio: 728/90</code>, <code>300/250</code>, <code>300/600</code> — cap it with <code>max-width</code>, and let the box scale proportionally in narrow columns. When the column can't honor a leaderboard at all, a container query swaps the slot for the 320×50 mobile unit. The column is the breakpoint, not the screen.</p>
<p>Unfilled inventory keeps the box too. A reserved slot that stays a quiet skeleton costs a few hundred square pixels; a collapsing slot costs a layout shift on every page where the auction passes. Publishers who measured both stopped collapsing years ago.</p>
</article>
<aside class="car-10__side" aria-label="Sidebar">
<p class="car-10__adlabel">Advertisement · half page 300×600</p>
<div class="car-10__slot car-10__slot--half">
<a class="car-10__ad car-10__ad--half" href="#car10-top" aria-label="House ad: Meridian data">
<b>Meridian Data</b><span>Your dashboards, minus the 40 tabs. Warehouse-native analytics for newsrooms.</span><i aria-hidden="true"></i><em>Book a demo →</em>
</a>
</div>
<div class="car-10__widget">
<h2>Most read</h2>
<ol><li><a href="#car10-top">Ratio maths for ad ops: the one-page cheat sheet</a></li><li><a href="#car10-top">Why the 320×50 still rules mobile</a></li><li><a href="#car10-top">Skeletons that convert better than spinners</a></li></ol>
</div>
</aside>
</main>
<footer class="car-10__foot">Slots reserve with <code>aspect-ratio</code> + <code>max-width</code>; creatives arrive whenever they like. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>
```
## CSS
```css
.car-10,
.car-10 *,
.car-10 *::before,
.car-10 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-10 {
--bg: oklch(0.97 0.004 250);
--ink: oklch(0.22 0.015 260);
--mut: oklch(0.5 0.012 260);
--line: oklch(0.89 0.008 255);
--acc: oklch(0.55 0.17 255);
--skeleton: oklch(0.93 0.006 255);
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-10__stage {
width: 100%;
container: car10/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-10__bar {
display: flex;
align-items: center;
gap: 18px;
padding: 14px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
background: oklch(1 0 0);
}
.car-10__brand {
font-size: 17px;
font-weight: 800;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
}
.car-10__nav {
display: flex;
gap: 2px;
margin-inline: auto;
}
.car-10__nav a {
display: grid;
place-items: center;
min-height: 44px;
padding: 0 12px;
border-radius: 9px;
font-size: 13px;
font-weight: 600;
color: var(--mut);
text-decoration: none;
transition: color .2s,background .2s;
}
.car-10__nav a:hover,
.car-10__nav a:focus-visible {
color: var(--ink);
background: oklch(0.94 0.006 255);
}
.car-10__nav a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
}
.car-10__sub {
display: grid;
place-items: center;
min-height: 40px;
padding: 0 16px;
border-radius: 99px;
background: var(--ink);
color: oklch(0.98 0 0);
font-size: 12.5px;
font-weight: 700;
text-decoration: none;
transition: background .2s;
}
.car-10__sub:hover,
.car-10__sub:focus-visible {
background: var(--acc);
}
.car-10__sub:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.car-10__slotzone {
padding: 16px clamp(16px,4cqi,44px) 4px;
text-align: center;
}
.car-10__slotzone--inline {
padding: 18px 0 6px;
}
.car-10__adlabel {
font-size: 9.5px;
font-weight: 700;
letter-spacing: .14em;
text-transform: uppercase;
color: oklch(0.62 0.01 260);
margin-bottom: 6px;
}
.car-10__slot {
position: relative;
margin-inline: auto;
border: 1px dashed oklch(0.82 0.01 255);
border-radius: 8px;
overflow: hidden;
background: linear-gradient(110deg,var(--skeleton) 30%,oklch(0.96 0.004 255) 45%,var(--skeleton) 60%) 0 0/200% 100%;
animation: car10-shimmer 1.6s linear infinite;
}
@keyframes car10-shimmer {
to {
background-position: -200% 0;
}
}
.car-10__slot--leader {
aspect-ratio: 728/90;
max-width: 728px;
}
.car-10__slot--mrec {
aspect-ratio: 300/250;
max-width: 300px;
}
.car-10__slot--half {
aspect-ratio: 300/600;
max-width: 300px;
}
.car-10__ad {
position: absolute;
inset: 0;
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
text-decoration: none;
color: oklch(0.98 0 0);
opacity: 0;
animation: car10-arrive .5s ease 1.4s both;
}
@keyframes car10-arrive {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.car-10__ad--leader {
background: linear-gradient(100deg,oklch(0.35 0.08 150),oklch(0.5 0.11 130));
justify-content: center;
text-align: left;
}
.car-10__ad--leader b {
font-size: clamp(14px,2.4cqi,19px);
letter-spacing: .22em;
}
.car-10__ad--leader span {
font-size: clamp(10px,1.8cqi,13px);
opacity: .92;
max-width: 46ch;
}
.car-10__ad--leader em {
font-style: normal;
font-size: clamp(10px,1.7cqi,12.5px);
font-weight: 700;
padding: 7px 12px;
border-radius: 99px;
background: oklch(0.98 0 0/.16);
border: 1px solid oklch(0.98 0 0/.4);
white-space: nowrap;
}
.car-10__ad--mrec {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
gap: 4px;
padding: 14px;
background: oklch(0.3 0.05 280);
animation-delay: 2s;
}
.car-10__ad--mrec i {
position: absolute;
inset: 0;
background: linear-gradient(oklch(0.2 0.04 280/.15),oklch(0.14 0.04 280/.85)),var(--img);
background-size: cover;
background-position: center;
z-index: -1;
margin: 0;
}
.car-10__ad--mrec b {
font-size: 17px;
letter-spacing: -.01em;
}
.car-10__ad--mrec span {
font-size: 11.5px;
line-height: 1.45;
opacity: .92;
}
.car-10__ad--mrec em {
font-style: normal;
font-size: 11.5px;
font-weight: 700;
margin-top: 6px;
padding: 8px 12px;
border-radius: 8px;
background: oklch(0.98 0 0);
color: oklch(0.3 0.05 280);
}
.car-10__ad--half {
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 8px;
padding: 22px;
background: linear-gradient(170deg,oklch(0.28 0.06 255),oklch(0.42 0.12 285));
animation-delay: 2.2s;
}
.car-10__ad--half b {
font-size: 19px;
letter-spacing: -.01em;
}
.car-10__ad--half span {
font-size: 12.5px;
line-height: 1.55;
opacity: .92;
}
.car-10__ad--half i {
width: 100%;
aspect-ratio: 1;
border-radius: 12px;
margin: 8px 0;
background: radial-gradient(60% 60% at 35% 30%,oklch(0.85 0.1 285/.5),transparent 70%),conic-gradient(from 200deg,oklch(0.5 0.14 285),oklch(0.65 0.16 255),oklch(0.5 0.14 285));
border: 1px solid oklch(0.98 0 0/.25);
}
.car-10__ad--half em {
font-style: normal;
font-size: 12px;
font-weight: 700;
padding: 9px 14px;
border-radius: 9px;
background: oklch(0.98 0 0);
color: oklch(0.32 0.08 270);
}
.car-10__ad:hover em,
.car-10__ad:focus-visible em {
translate: 2px 0;
}
.car-10__ad em {
transition: translate .2s;
}
.car-10__ad:focus-visible {
outline: 3px solid var(--acc);
outline-offset: -3px;
}
.car-10__main {
display: grid;
grid-template-columns: minmax(0,1fr) 332px;
gap: clamp(20px,3.5cqi,40px);
max-width: 1120px;
margin-inline: auto;
padding: clamp(18px,3cqi,32px) clamp(16px,4cqi,44px);
align-items: start;
}
.car-10__kicker {
font-size: 11px;
font-weight: 700;
letter-spacing: .15em;
text-transform: uppercase;
color: var(--acc);
}
.car-10__article h1 {
font-size: clamp(24px,3.6cqi,36px);
line-height: 1.12;
letter-spacing: -.025em;
font-weight: 800;
margin-top: 8px;
text-wrap: balance;
}
.car-10__meta {
font-size: 12.5px;
color: var(--mut);
margin: 8px 0 4px;
}
.car-10__article > p {
font-size: 15px;
line-height: 1.7;
margin-top: 16px;
max-width: 66ch;
}
.car-10__article code,
.car-10__foot code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .88em;
background: oklch(0.92 0.008 255);
padding: 2px 6px;
border-radius: 5px;
color: oklch(0.42 0.12 255);
}
.car-10__side {
display: flex;
flex-direction: column;
gap: 18px;
text-align: center;
}
.car-10__widget {
text-align: left;
border: 1px solid var(--line);
border-radius: 14px;
padding: 16px;
background: oklch(1 0 0);
}
.car-10__widget h2 {
font-size: 12px;
font-weight: 800;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
}
.car-10__widget ol {
list-style: none;
counter-reset: mr;
}
.car-10__widget li {
counter-increment: mr;
display: flex;
gap: 10px;
padding: 9px 0;
border-top: 1px solid var(--line);
}
.car-10__widget li::before {
content: counter(mr,decimal-leading-zero);
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
color: var(--acc);
padding-top: 2px;
}
.car-10__widget a {
font-size: 13px;
font-weight: 600;
line-height: 1.4;
color: inherit;
text-decoration: none;
}
.car-10__widget a:hover,
.car-10__widget a:focus-visible {
color: var(--acc);
text-decoration: underline;
text-underline-offset: 3px;
}
.car-10__widget a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
border-radius: 2px;
}
.car-10__foot {
max-width: 1120px;
margin-inline: auto;
padding: 16px clamp(16px,4cqi,44px) 32px;
border-top: 1px solid var(--line);
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
}
@container car10 (width < 560px) {
.car-10__slot--leader {
aspect-ratio: 320/50;
max-width: 320px;
}
.car-10__ad--leader span {
display: none;
}
}
@container car10 (width < 880px) {
.car-10__main {
grid-template-columns: 1fr;
}
.car-10__nav {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.car-10__slot {
animation: none;
}
.car-10__ad {
animation-duration: .01ms;
animation-delay: .5s;
}
.car-10 * {
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 Ad Banner Container
Source: https://codefronts.com/layouts/css-aspect-ratio/css-aspect-ratio-ad-banner-container/
Publisher-grade ad slots that reserve their exact space before a single ad byte arrives: aspect-ratio: 728/90 for the leaderboard, 300/250 for the rectangle, 300/600 for the half-page — the raw IAB dimensions written straight into CSS, no decimal maths. Each slot shimmers as a labeled placeholder, the 'ad' arrives on a CSS delay to prove the page doesn't flinch, and a container query swaps the leaderboard for a 320/50 mobile banner when the column gets narrow. Ads pay the bills; this is how they stop costing you CLS.
## HTML
```html
<section class="car-10" aria-label="Ad banner container demo">
<div class="car-10__stage" id="car10-top">
<header class="car-10__bar">
<a class="car-10__brand" href="#car10-top">The Morning Brief</a>
<nav class="car-10__nav" aria-label="Sections"><a href="#car10-top">Media</a><a href="#car10-top">Adtech</a><a href="#car10-top">Metrics</a></nav>
<a class="car-10__sub" href="#car10-top">Subscribe</a>
</header>
<div class="car-10__slotzone">
<p class="car-10__adlabel">Advertisement · leaderboard 728×90 (320×50 when narrow)</p>
<div class="car-10__slot car-10__slot--leader">
<a class="car-10__ad car-10__ad--leader" href="#car10-top" aria-label="House ad: Fjell boots">
<b>FJELL</b><span>Boots that outlast the trail. Guaranteed for a decade.</span><em>Shop now →</em>
</a>
</div>
</div>
<main class="car-10__main">
<article class="car-10__article">
<p class="car-10__kicker">Adtech · CLS</p>
<h1>The cheapest ranking win in publishing is an empty box</h1>
<p class="car-10__meta">By Harriet Cole · August 3, 2026</p>
<p>Every slot on this page was full-size before the auction returned. The leaderboard above, the rectangle below, the half-page in the sidebar — each is an <code>aspect-ratio</code> reservation wearing a skeleton, which is why the paragraph you are reading has not moved since first paint.</p>
<p>Watch the creatives arrive (they're on a deliberate 1.4–2.2s delay). The boxes don't grow, the article doesn't lurch, and the CLS report stays at zero — the exact failure mode that used to cost publishers a Core Web Vitals grade every time a bid resolved late.</p>
<div class="car-10__slotzone car-10__slotzone--inline">
<p class="car-10__adlabel">Advertisement · medium rectangle 300×250</p>
<div class="car-10__slot car-10__slot--mrec">
<a class="car-10__ad car-10__ad--mrec" href="#car10-top" aria-label="House ad: Mono focus app" style="--img:url('https://images.unsplash.com/photo-1553062407-98eeb64c6a62?q=80&w=600&h=500&auto=format&fit=crop')">
<i aria-hidden="true"></i><b>Mono</b><span>One task at a time. The focus app for deadline weeks.</span><em>Try free →</em>
</a>
</div>
</div>
<p>The trick bears repeating because it's so unglamorous: write the IAB size into the ratio — <code>aspect-ratio: 728/90</code>, <code>300/250</code>, <code>300/600</code> — cap it with <code>max-width</code>, and let the box scale proportionally in narrow columns. When the column can't honor a leaderboard at all, a container query swaps the slot for the 320×50 mobile unit. The column is the breakpoint, not the screen.</p>
<p>Unfilled inventory keeps the box too. A reserved slot that stays a quiet skeleton costs a few hundred square pixels; a collapsing slot costs a layout shift on every page where the auction passes. Publishers who measured both stopped collapsing years ago.</p>
</article>
<aside class="car-10__side" aria-label="Sidebar">
<p class="car-10__adlabel">Advertisement · half page 300×600</p>
<div class="car-10__slot car-10__slot--half">
<a class="car-10__ad car-10__ad--half" href="#car10-top" aria-label="House ad: Meridian data">
<b>Meridian Data</b><span>Your dashboards, minus the 40 tabs. Warehouse-native analytics for newsrooms.</span><i aria-hidden="true"></i><em>Book a demo →</em>
</a>
</div>
<div class="car-10__widget">
<h2>Most read</h2>
<ol><li><a href="#car10-top">Ratio maths for ad ops: the one-page cheat sheet</a></li><li><a href="#car10-top">Why the 320×50 still rules mobile</a></li><li><a href="#car10-top">Skeletons that convert better than spinners</a></li></ol>
</div>
</aside>
</main>
<footer class="car-10__foot">Slots reserve with <code>aspect-ratio</code> + <code>max-width</code>; creatives arrive whenever they like. A demo from the CodeFronts aspect-ratio collection.</footer>
</div>
</section>
```
## CSS
```css
.car-10,
.car-10 *,
.car-10 *::before,
.car-10 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.car-10 {
--bg: oklch(0.97 0.004 250);
--ink: oklch(0.22 0.015 260);
--mut: oklch(0.5 0.012 260);
--line: oklch(0.89 0.008 255);
--acc: oklch(0.55 0.17 255);
--skeleton: oklch(0.93 0.006 255);
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-10__stage {
width: 100%;
container: car10/inline-size;
height: 100vh;
height: 100svh;
overflow-y: auto;
background: var(--bg);
}
.car-10__bar {
display: flex;
align-items: center;
gap: 18px;
padding: 14px clamp(16px,4cqi,44px);
border-bottom: 1px solid var(--line);
background: oklch(1 0 0);
}
.car-10__brand {
font-size: 17px;
font-weight: 800;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
}
.car-10__nav {
display: flex;
gap: 2px;
margin-inline: auto;
}
.car-10__nav a {
display: grid;
place-items: center;
min-height: 44px;
padding: 0 12px;
border-radius: 9px;
font-size: 13px;
font-weight: 600;
color: var(--mut);
text-decoration: none;
transition: color .2s,background .2s;
}
.car-10__nav a:hover,
.car-10__nav a:focus-visible {
color: var(--ink);
background: oklch(0.94 0.006 255);
}
.car-10__nav a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: -2px;
}
.car-10__sub {
display: grid;
place-items: center;
min-height: 40px;
padding: 0 16px;
border-radius: 99px;
background: var(--ink);
color: oklch(0.98 0 0);
font-size: 12.5px;
font-weight: 700;
text-decoration: none;
transition: background .2s;
}
.car-10__sub:hover,
.car-10__sub:focus-visible {
background: var(--acc);
}
.car-10__sub:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.car-10__slotzone {
padding: 16px clamp(16px,4cqi,44px) 4px;
text-align: center;
}
.car-10__slotzone--inline {
padding: 18px 0 6px;
}
.car-10__adlabel {
font-size: 9.5px;
font-weight: 700;
letter-spacing: .14em;
text-transform: uppercase;
color: oklch(0.62 0.01 260);
margin-bottom: 6px;
}
.car-10__slot {
position: relative;
margin-inline: auto;
border: 1px dashed oklch(0.82 0.01 255);
border-radius: 8px;
overflow: hidden;
background: linear-gradient(110deg,var(--skeleton) 30%,oklch(0.96 0.004 255) 45%,var(--skeleton) 60%) 0 0/200% 100%;
animation: car10-shimmer 1.6s linear infinite;
}
@keyframes car10-shimmer {
to {
background-position: -200% 0;
}
}
.car-10__slot--leader {
aspect-ratio: 728/90;
max-width: 728px;
}
.car-10__slot--mrec {
aspect-ratio: 300/250;
max-width: 300px;
}
.car-10__slot--half {
aspect-ratio: 300/600;
max-width: 300px;
}
.car-10__ad {
position: absolute;
inset: 0;
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
text-decoration: none;
color: oklch(0.98 0 0);
opacity: 0;
animation: car10-arrive .5s ease 1.4s both;
}
@keyframes car10-arrive {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.car-10__ad--leader {
background: linear-gradient(100deg,oklch(0.35 0.08 150),oklch(0.5 0.11 130));
justify-content: center;
text-align: left;
}
.car-10__ad--leader b {
font-size: clamp(14px,2.4cqi,19px);
letter-spacing: .22em;
}
.car-10__ad--leader span {
font-size: clamp(10px,1.8cqi,13px);
opacity: .92;
max-width: 46ch;
}
.car-10__ad--leader em {
font-style: normal;
font-size: clamp(10px,1.7cqi,12.5px);
font-weight: 700;
padding: 7px 12px;
border-radius: 99px;
background: oklch(0.98 0 0/.16);
border: 1px solid oklch(0.98 0 0/.4);
white-space: nowrap;
}
.car-10__ad--mrec {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
gap: 4px;
padding: 14px;
background: oklch(0.3 0.05 280);
animation-delay: 2s;
}
.car-10__ad--mrec i {
position: absolute;
inset: 0;
background: linear-gradient(oklch(0.2 0.04 280/.15),oklch(0.14 0.04 280/.85)),var(--img);
background-size: cover;
background-position: center;
z-index: -1;
margin: 0;
}
.car-10__ad--mrec b {
font-size: 17px;
letter-spacing: -.01em;
}
.car-10__ad--mrec span {
font-size: 11.5px;
line-height: 1.45;
opacity: .92;
}
.car-10__ad--mrec em {
font-style: normal;
font-size: 11.5px;
font-weight: 700;
margin-top: 6px;
padding: 8px 12px;
border-radius: 8px;
background: oklch(0.98 0 0);
color: oklch(0.3 0.05 280);
}
.car-10__ad--half {
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 8px;
padding: 22px;
background: linear-gradient(170deg,oklch(0.28 0.06 255),oklch(0.42 0.12 285));
animation-delay: 2.2s;
}
.car-10__ad--half b {
font-size: 19px;
letter-spacing: -.01em;
}
.car-10__ad--half span {
font-size: 12.5px;
line-height: 1.55;
opacity: .92;
}
.car-10__ad--half i {
width: 100%;
aspect-ratio: 1;
border-radius: 12px;
margin: 8px 0;
background: radial-gradient(60% 60% at 35% 30%,oklch(0.85 0.1 285/.5),transparent 70%),conic-gradient(from 200deg,oklch(0.5 0.14 285),oklch(0.65 0.16 255),oklch(0.5 0.14 285));
border: 1px solid oklch(0.98 0 0/.25);
}
.car-10__ad--half em {
font-style: normal;
font-size: 12px;
font-weight: 700;
padding: 9px 14px;
border-radius: 9px;
background: oklch(0.98 0 0);
color: oklch(0.32 0.08 270);
}
.car-10__ad:hover em,
.car-10__ad:focus-visible em {
translate: 2px 0;
}
.car-10__ad em {
transition: translate .2s;
}
.car-10__ad:focus-visible {
outline: 3px solid var(--acc);
outline-offset: -3px;
}
.car-10__main {
display: grid;
grid-template-columns: minmax(0,1fr) 332px;
gap: clamp(20px,3.5cqi,40px);
max-width: 1120px;
margin-inline: auto;
padding: clamp(18px,3cqi,32px) clamp(16px,4cqi,44px);
align-items: start;
}
.car-10__kicker {
font-size: 11px;
font-weight: 700;
letter-spacing: .15em;
text-transform: uppercase;
color: var(--acc);
}
.car-10__article h1 {
font-size: clamp(24px,3.6cqi,36px);
line-height: 1.12;
letter-spacing: -.025em;
font-weight: 800;
margin-top: 8px;
text-wrap: balance;
}
.car-10__meta {
font-size: 12.5px;
color: var(--mut);
margin: 8px 0 4px;
}
.car-10__article > p {
font-size: 15px;
line-height: 1.7;
margin-top: 16px;
max-width: 66ch;
}
.car-10__article code,
.car-10__foot code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .88em;
background: oklch(0.92 0.008 255);
padding: 2px 6px;
border-radius: 5px;
color: oklch(0.42 0.12 255);
}
.car-10__side {
display: flex;
flex-direction: column;
gap: 18px;
text-align: center;
}
.car-10__widget {
text-align: left;
border: 1px solid var(--line);
border-radius: 14px;
padding: 16px;
background: oklch(1 0 0);
}
.car-10__widget h2 {
font-size: 12px;
font-weight: 800;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
}
.car-10__widget ol {
list-style: none;
counter-reset: mr;
}
.car-10__widget li {
counter-increment: mr;
display: flex;
gap: 10px;
padding: 9px 0;
border-top: 1px solid var(--line);
}
.car-10__widget li::before {
content: counter(mr,decimal-leading-zero);
font-family: ui-monospace,Menlo,monospace;
font-size: 11px;
font-weight: 700;
color: var(--acc);
padding-top: 2px;
}
.car-10__widget a {
font-size: 13px;
font-weight: 600;
line-height: 1.4;
color: inherit;
text-decoration: none;
}
.car-10__widget a:hover,
.car-10__widget a:focus-visible {
color: var(--acc);
text-decoration: underline;
text-underline-offset: 3px;
}
.car-10__widget a:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
border-radius: 2px;
}
.car-10__foot {
max-width: 1120px;
margin-inline: auto;
padding: 16px clamp(16px,4cqi,44px) 32px;
border-top: 1px solid var(--line);
font-size: 12.5px;
line-height: 1.7;
color: var(--mut);
}
@container car10 (width < 560px) {
.car-10__slot--leader {
aspect-ratio: 320/50;
max-width: 320px;
}
.car-10__ad--leader span {
display: none;
}
}
@container car10 (width < 880px) {
.car-10__main {
grid-template-columns: 1fr;
}
.car-10__nav {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.car-10__slot {
animation: none;
}
.car-10__ad {
animation-duration: .01ms;
animation-delay: .5s;
}
.car-10 * {
transition-duration: .01ms !important;
}
}
```How this works
Ad scripts are the worst-behaved late content on the web — they inject an iframe of known size at an unknown time. The fix is pre-booking the box, and aspect-ratio happily takes IAB dimensions verbatim:
.slot { margin-inline:auto; background:var(--skeleton); }
.slot--leader{ aspect-ratio:728 / 90; max-width:728px; }
.slot--mrec { aspect-ratio:300 / 250; max-width:300px; }
.slot--half { aspect-ratio:300 / 600; max-width:300px; }
@container article (width < 560px){
.slot--leader{ aspect-ratio:320 / 50; max-width:320px; } /* mobile banner */
}Two details make this production-real. First, aspect-ratio accepts any two numbers — nobody converts 728×90 to 8.088̄:1; you write the creative's pixel spec and move on. Second, the pairing of ratio + max-width means the slot renders at exactly 728×90 when the column affords it and scales down proportionally when it doesn't — matching how responsive ad units actually serve (they pick the largest creative that fits the measured width). The page reserves the worst case; the ad fills it; CLS stays 0.000 whether the auction takes 80ms or 8 seconds — or never fills at all.
The swap at narrow widths is a container query, not a media query, because ad slots live in columns: the same leaderboard slot dropped into a 300px sidebar must become a mobile banner even on a 4K screen. The slot's own column is the truth, so the column is the container. The demo's 'creatives' are CSS-delayed house ads (animation-delay:1.4s) so you can watch the reservation absorb the arrival; in production the same box wraps your googletag div and nothing about the CSS changes.
Make it yours
- Full IAB set: billboard
970/250, large leaderboard970/90, skyscraper160/600, mobile large320/100— one class each, same recipe. - Collapse policy: if unfilled slots should vanish after the auction, have the ad script add a .filled class and give the base slot
transition:max-height— but know that collapsing IS layout shift; most publishers keep the box. - Skeleton tone: the shimmer reads as 'loading'; a flat
var(--line)tint with the label reads as 'reserved'. Regulated markets often require the visible 'Advertisement' label either way — it's baked into the slot header here. - House-ad fallback: this demo's delayed creatives double as a real pattern — render your own promo in the slot and let the ad script replace it, so unfilled inventory still earns.
Gotchas — read before shipping
- Reserve the size you actually serve: booking 728×90 and then loading a 970×250 creative shifts the page anyway. The slot map and the CSS must come from the same config.
- Ad iframes are fixed-size — the slot scales, the creative doesn't. Below 728px the leaderboard BOX shrinks proportionally but a real 728px creative would be cropped; that's why the container query swaps to the 320/50 unit instead of letting the box shrink alone.
- Don't put the 'Advertisement' label inside the reserved box if your ad partner measures viewability by pixel coverage — the label steals visible area. It sits above the box here.
- aspect-ratio reserves layout, not paint: a pure-white empty slot can still 'flash' when the creative paints. The skeleton background is what makes the wait look intentional.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by oklch(), @container, text-wrap as this demo is written. The core technique itself goes back further — Chrome 111+.
aspect-ratio and max-width are 2021-universal; container queries are Chrome 105 / Safari 16 / Firefox 110. Floor reflects oklch()/color-mix() tokens. Without container query support the leaderboard simply scales down proportionally — still zero CLS.