22 CSS Headers15 / 22
Full Screen Overlay Hamburger Header
A header that opens into a full-screen navigation overlay with no JavaScript: a visually hidden checkbox, a label styled as the hamburger, and :has(:checked) on the root. The bars morph into an X with a spring curve, menu items stagger in on animation-delay, and the closed overlay is hidden with visibility so its links never sit in the tab order.
Published Updated
The code
<div class="hd-15">
<a class="hd-15__skip" href="#hd-15-main">Skip to content</a>
<input class="hd-15__sr" type="checkbox" id="hd-15-open" aria-label="Open navigation menu">
<header class="hd-15__bar">
<a class="hd-15__brand" href="#hd-15-main">
<span class="hd-15__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" focusable="false"><path d="M12 3.5 20.5 12 12 20.5 3.5 12 12 3.5Z" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="2.6" fill="currentColor"/></svg>
</span>
<span class="hd-15__word">Vantage</span>
</a>
<p class="hd-15__tag">Studio for interface engineering</p>
<input class="hd-15__sr" type="checkbox" id="hd-15-light">
<label class="hd-15__theme" for="hd-15-light">
<svg class="hd-15__moon" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M20.5 14.4A8.4 8.4 0 0 1 9.6 3.5 8.6 8.6 0 1 0 20.5 14.4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
<svg class="hd-15__sun" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4.2" stroke="currentColor" stroke-width="1.8"/><path d="M12 2.8v2.1M12 19.1v2.1M2.8 12h2.1M19.1 12h2.1M5.5 5.5 7 7M17 17l1.5 1.5M18.5 5.5 17 7M7 17l-1.5 1.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Switch light or dark theme</span>
</label>
<label class="hd-15__burger" for="hd-15-open">
<span class="hd-15__bars" aria-hidden="true">
<span class="hd-15__b1"></span><span class="hd-15__b2"></span><span class="hd-15__b3"></span>
</span>
<span class="hd-15__burger-t" aria-hidden="true">Menu</span>
</label>
</header>
<div class="hd-15__overlay">
<label class="hd-15__close-all" for="hd-15-open" aria-label="Close navigation menu"></label>
<div class="hd-15__overlay-in">
<nav class="hd-15__menu" aria-label="Main">
<ul>
<li style="--i:1"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">01</span>Work</a></li>
<li style="--i:2"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">02</span>Services</a></li>
<li style="--i:3"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">03</span>Studio</a></li>
<li style="--i:4"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">04</span>Writing</a></li>
<li style="--i:5"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">05</span>Contact</a></li>
</ul>
</nav>
<div class="hd-15__meta" style="--i:6">
<p class="hd-15__meta-h">Studio</p>
<p>Unit 4, Ropewalk<br>Bristol BS1 6QT</p>
<p class="hd-15__meta-h">New work</p>
<p>hello@vantage.studio<br>+44 117 496 0142</p>
</div>
</div>
<label class="hd-15__close" for="hd-15-open">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Close navigation menu</span>
</label>
</div>
<main class="hd-15__main" id="hd-15-main">
<p class="hd-15__eyebrow">Selected work · 2026</p>
<h1>Interfaces that survive the second release.</h1>
<p class="hd-15__lead">Press the menu button — or tab to it and hit space. The bars morph, the overlay blurs the page and five links stagger in. Nothing here is JavaScript.</p>
<ul class="hd-15__work">
<li><span class="hd-15__w-n">01</span><span class="hd-15__w-t">Northwind — freight console</span><span class="hd-15__w-y">2026</span></li>
<li><span class="hd-15__w-n">02</span><span class="hd-15__w-t">Halcyon — design system</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">03</span><span class="hd-15__w-t">Meridian — docs platform</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">04</span><span class="hd-15__w-t">Foundry — asset pipeline</span><span class="hd-15__w-y">2024</span></li>
</ul>
<div class="hd-15__filler" aria-hidden="true"></div>
</main>
</div><div class="hd-15">
<a class="hd-15__skip" href="#hd-15-main">Skip to content</a>
<input class="hd-15__sr" type="checkbox" id="hd-15-open" aria-label="Open navigation menu">
<header class="hd-15__bar">
<a class="hd-15__brand" href="#hd-15-main">
<span class="hd-15__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" focusable="false"><path d="M12 3.5 20.5 12 12 20.5 3.5 12 12 3.5Z" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="2.6" fill="currentColor"/></svg>
</span>
<span class="hd-15__word">Vantage</span>
</a>
<p class="hd-15__tag">Studio for interface engineering</p>
<input class="hd-15__sr" type="checkbox" id="hd-15-light">
<label class="hd-15__theme" for="hd-15-light">
<svg class="hd-15__moon" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M20.5 14.4A8.4 8.4 0 0 1 9.6 3.5 8.6 8.6 0 1 0 20.5 14.4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
<svg class="hd-15__sun" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4.2" stroke="currentColor" stroke-width="1.8"/><path d="M12 2.8v2.1M12 19.1v2.1M2.8 12h2.1M19.1 12h2.1M5.5 5.5 7 7M17 17l1.5 1.5M18.5 5.5 17 7M7 17l-1.5 1.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Switch light or dark theme</span>
</label>
<label class="hd-15__burger" for="hd-15-open">
<span class="hd-15__bars" aria-hidden="true">
<span class="hd-15__b1"></span><span class="hd-15__b2"></span><span class="hd-15__b3"></span>
</span>
<span class="hd-15__burger-t" aria-hidden="true">Menu</span>
</label>
</header>
<div class="hd-15__overlay">
<label class="hd-15__close-all" for="hd-15-open" aria-label="Close navigation menu"></label>
<div class="hd-15__overlay-in">
<nav class="hd-15__menu" aria-label="Main">
<ul>
<li style="--i:1"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">01</span>Work</a></li>
<li style="--i:2"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">02</span>Services</a></li>
<li style="--i:3"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">03</span>Studio</a></li>
<li style="--i:4"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">04</span>Writing</a></li>
<li style="--i:5"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">05</span>Contact</a></li>
</ul>
</nav>
<div class="hd-15__meta" style="--i:6">
<p class="hd-15__meta-h">Studio</p>
<p>Unit 4, Ropewalk<br>Bristol BS1 6QT</p>
<p class="hd-15__meta-h">New work</p>
<p>hello@vantage.studio<br>+44 117 496 0142</p>
</div>
</div>
<label class="hd-15__close" for="hd-15-open">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Close navigation menu</span>
</label>
</div>
<main class="hd-15__main" id="hd-15-main">
<p class="hd-15__eyebrow">Selected work · 2026</p>
<h1>Interfaces that survive the second release.</h1>
<p class="hd-15__lead">Press the menu button — or tab to it and hit space. The bars morph, the overlay blurs the page and five links stagger in. Nothing here is JavaScript.</p>
<ul class="hd-15__work">
<li><span class="hd-15__w-n">01</span><span class="hd-15__w-t">Northwind — freight console</span><span class="hd-15__w-y">2026</span></li>
<li><span class="hd-15__w-n">02</span><span class="hd-15__w-t">Halcyon — design system</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">03</span><span class="hd-15__w-t">Meridian — docs platform</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">04</span><span class="hd-15__w-t">Foundry — asset pipeline</span><span class="hd-15__w-y">2024</span></li>
</ul>
<div class="hd-15__filler" aria-hidden="true"></div>
</main>
</div>.hd-15 {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
--menu-size: clamp(2.1rem,9vw,4.6rem);
--font-display: "Avenir Next Condensed","Arial Narrow",system-ui,sans-serif;
--font-body: system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
display: block;
position: relative;
background: var(--bg);
color: var(--ink);
font-family: var(--font-body);
line-height: 1.55;
}
@supports (color: oklch(50% .1 200)) {
.hd-15 {
--surface: oklch(14% .006 200);
--ink: oklch(97% .006 200);
--muted: oklch(68% .015 200);
--accent: oklch(84% .14 185);
}
}
.hd-15 * {
box-sizing: border-box;
}
.hd-15 h1,
.hd-15 p,
.hd-15 ul {
margin: 0;
padding: 0;
}
.hd-15 ul {
list-style: none;
}
.hd-15 [hidden] {
display: none;
}
.hd-15 :focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.hd-15__sr,
.hd-15__vh {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__skip {
position: absolute;
inset-inline-start: 1rem;
top: -3rem;
z-index: 80;
padding: .55rem 1rem;
background: var(--accent);
color: var(--accent-ink);
font-size: .8rem;
font-weight: 700;
text-decoration: none;
transition: top .18s ease;
}
.hd-15__skip:focus-visible {
top: 1rem;
}
/* ── header: no chrome, type only ─────────────────────────────────── */
.hd-15__bar {
position: sticky;
top: 0;
z-index: 60;
display: flex;
align-items: center;
gap: 1.5rem;
padding: clamp(1rem,3vw,1.5rem) clamp(1rem,4vw,2.5rem);
background: color-mix(in srgb, var(--bg) 78%, transparent);
backdrop-filter: blur(10px);
}
.hd-15__brand {
display: inline-flex;
align-items: center;
gap: .6rem;
color: var(--ink);
text-decoration: none;
min-inline-size: 0;
}
.hd-15__mark {
display: grid;
place-items: center;
inline-size: 1.9rem;
block-size: 1.9rem;
color: var(--accent);
flex: none;
}
.hd-15__mark svg {
inline-size: 1.9rem;
block-size: 1.9rem;
}
.hd-15__word {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__tag {
font-size: .72rem;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--muted);
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__burger {
display: inline-flex;
align-items: center;
gap: .6rem;
margin-inline-start: auto;
min-block-size: 2.75rem;
padding: .5rem .75rem;
border: 1px solid var(--line);
cursor: pointer;
transition: border-color .18s ease, background-color .18s ease;
}
.hd-15__burger:hover {
border-color: var(--accent);
background: rgba(34,224,208,.08);
}
.hd-15__bars {
display: grid;
gap: 4px;
inline-size: 1.4rem;
}
.hd-15__bars span {
display: block;
block-size: 2px;
background: var(--ink);
border-radius: 2px;
transition: translate .3s cubic-bezier(.5,-.35,.4,1.4), rotate .3s cubic-bezier(.5,-.35,.4,1.4), opacity .2s ease, scale .2s ease, background-color .2s ease;
}
.hd-15__burger-t {
font-family: var(--font-display);
font-size: .82rem;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: var(--muted);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b1 {
translate: 0 6px;
rotate: 45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b2 {
opacity: 0;
scale: .3 1;
}
.hd-15:has(#hd-15-open:checked) .hd-15__b3 {
translate: 0 -6px;
rotate: -45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:focus-visible) .hd-15__burger {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ── full-screen overlay ──────────────────────────────────────────── */
.hd-15__overlay {
position: fixed;
inset: 0;
z-index: 70;
display: grid;
align-items: center;
background: rgba(0,0,0,.94);
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: opacity .28s ease, visibility .28s allow-discrete;
}
@supports (backdrop-filter: blur(2px)) {
.hd-15__overlay {
background: rgba(0,0,0,.72);
backdrop-filter: blur(22px) saturate(120%);
}
}
.hd-15:has(#hd-15-open:checked) .hd-15__overlay {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.hd-15__close-all {
position: absolute;
inset: 0;
cursor: default;
}
.hd-15__overlay-in {
position: relative;
inline-size: 100%;
max-inline-size: 72rem;
margin-inline: auto;
display: grid;
grid-template-columns: minmax(0,1fr) 14rem;
gap: clamp(1.5rem,5vw,4rem);
align-items: end;
padding: clamp(2rem,8vh,5rem) clamp(1.25rem,5vw,3rem);
}
.hd-15__menu ul {
display: grid;
gap: .1rem;
}
.hd-15__link {
display: flex;
align-items: baseline;
gap: 1rem;
padding: .15rem 0;
font-family: var(--font-display);
font-size: var(--menu-size);
line-height: 1.05;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
color: var(--ink);
text-decoration: none;
transition: color .18s ease, translate .18s ease;
}
.hd-15__link:hover {
color: var(--accent);
translate: .6rem 0;
}
.hd-15__num {
font-family: var(--font-body);
font-size: .8rem;
font-weight: 600;
letter-spacing: .14em;
color: var(--muted);
flex: none;
}
.hd-15__meta {
display: grid;
gap: .25rem;
color: var(--muted);
font-size: .85rem;
}
.hd-15__meta-h {
font-size: .68rem;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--accent);
margin-top: .75rem;
}
.hd-15__meta-h:first-child {
margin-top: 0;
}
.hd-15__close {
position: absolute;
top: clamp(1rem,3vw,1.5rem);
inset-inline-end: clamp(1rem,4vw,2.5rem);
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 1px solid var(--line);
color: var(--ink);
cursor: pointer;
transition: border-color .18s ease, color .18s ease;
}
.hd-15__close svg {
inline-size: 1.3rem;
block-size: 1.3rem;
}
.hd-15__close:hover {
border-color: var(--accent);
color: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__link,
.hd-15:has(#hd-15-open:checked) .hd-15__meta {
animation: hd-15-in .45s cubic-bezier(.2,.8,.2,1) backwards;
animation-delay: calc(var(--i,1) * 55ms + 80ms);
}
@keyframes hd-15-in {
from {
opacity: 0;
translate: 0 1.4rem;
}
}
/* ── page body ────────────────────────────────────────────────────── */
.hd-15__main {
max-inline-size: 64rem;
margin-inline: auto;
padding: clamp(3rem,9vw,6rem) clamp(1.25rem,4vw,2.5rem) 5rem;
}
.hd-15__eyebrow {
font-size: .72rem;
font-weight: 700;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--accent);
}
.hd-15__main h1 {
font-family: var(--font-display);
font-size: clamp(2.2rem,8vw,4.4rem);
line-height: 1.02;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
margin-top: 1rem;
max-inline-size: 22ch;
text-wrap: balance;
}
.hd-15__lead {
margin-top: 1.2rem;
max-inline-size: 52ch;
color: var(--muted);
font-size: 1.02rem;
text-wrap: pretty;
}
.hd-15__work {
margin-top: clamp(2.5rem,7vw,4rem);
border-top: 1px solid var(--line);
}
.hd-15__work li {
display: grid;
grid-template-columns: 3rem minmax(0,1fr) 4rem;
align-items: center;
gap: 1rem;
padding: 1rem .25rem;
border-bottom: 1px solid var(--line);
}
.hd-15__work li:hover {
background: var(--surface);
}
.hd-15__w-n {
font-size: .75rem;
letter-spacing: .14em;
color: var(--muted);
}
.hd-15__w-t {
font-family: var(--font-display);
font-size: 1.25rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .02em;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__w-y {
font-size: .8rem;
color: var(--muted);
text-align: end;
font-variant-numeric: tabular-nums;
}
.hd-15__filler {
block-size: 40vh;
}
@media (max-width: 720px) {
.hd-15__tag {
display: none;
}
.hd-15__overlay-in {
grid-template-columns: minmax(0,1fr);
align-items: start;
}
.hd-15__meta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.hd-15 * {
animation-duration: 1ms !important;
transition-duration: 1ms !important;
}
}
@media (forced-colors: active) {
.hd-15__overlay {
background: Canvas;
}
.hd-15__burger,
.hd-15__close {
border: 1px solid CanvasText;
}
}
/* ── manual theme toggle — beats the OS default ──────────────────── */
.hd-15:has(#hd-15-light:checked) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* icon: shows the scheme the toggle will switch you to */
.hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: block;
}
@media (prefers-color-scheme: light) {
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* FLIP-BACK — light OS + checked toggle returns to the dark surface */
.hd-15:has(#hd-15-light:checked) {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
}
/* the icon always offers the scheme you are not in */
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__sun {
display: none;
}
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__moon {
display: block;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: block;
}
}
.hd-15[data-theme="light"] {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* ── theme toggle — visually hidden checkbox, zero JS ────────────── */
.hd-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__theme {
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 0;
border-radius: 999px;
background: transparent;
color: inherit;
cursor: pointer;
transition: background-color .18s ease;
}
.hd-15__theme svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.hd-15__theme:hover {
background: rgba(128,128,128,.16);
}
.hd-15:has(#hd-15-light:focus-visible) .hd-15__theme {
outline: 2px solid currentColor;
outline-offset: 2px;
}.hd-15 {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
--menu-size: clamp(2.1rem,9vw,4.6rem);
--font-display: "Avenir Next Condensed","Arial Narrow",system-ui,sans-serif;
--font-body: system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
display: block;
position: relative;
background: var(--bg);
color: var(--ink);
font-family: var(--font-body);
line-height: 1.55;
}
@supports (color: oklch(50% .1 200)) {
.hd-15 {
--surface: oklch(14% .006 200);
--ink: oklch(97% .006 200);
--muted: oklch(68% .015 200);
--accent: oklch(84% .14 185);
}
}
.hd-15 * {
box-sizing: border-box;
}
.hd-15 h1,
.hd-15 p,
.hd-15 ul {
margin: 0;
padding: 0;
}
.hd-15 ul {
list-style: none;
}
.hd-15 [hidden] {
display: none;
}
.hd-15 :focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.hd-15__sr,
.hd-15__vh {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__skip {
position: absolute;
inset-inline-start: 1rem;
top: -3rem;
z-index: 80;
padding: .55rem 1rem;
background: var(--accent);
color: var(--accent-ink);
font-size: .8rem;
font-weight: 700;
text-decoration: none;
transition: top .18s ease;
}
.hd-15__skip:focus-visible {
top: 1rem;
}
/* ── header: no chrome, type only ─────────────────────────────────── */
.hd-15__bar {
position: sticky;
top: 0;
z-index: 60;
display: flex;
align-items: center;
gap: 1.5rem;
padding: clamp(1rem,3vw,1.5rem) clamp(1rem,4vw,2.5rem);
background: color-mix(in srgb, var(--bg) 78%, transparent);
backdrop-filter: blur(10px);
}
.hd-15__brand {
display: inline-flex;
align-items: center;
gap: .6rem;
color: var(--ink);
text-decoration: none;
min-inline-size: 0;
}
.hd-15__mark {
display: grid;
place-items: center;
inline-size: 1.9rem;
block-size: 1.9rem;
color: var(--accent);
flex: none;
}
.hd-15__mark svg {
inline-size: 1.9rem;
block-size: 1.9rem;
}
.hd-15__word {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__tag {
font-size: .72rem;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--muted);
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__burger {
display: inline-flex;
align-items: center;
gap: .6rem;
margin-inline-start: auto;
min-block-size: 2.75rem;
padding: .5rem .75rem;
border: 1px solid var(--line);
cursor: pointer;
transition: border-color .18s ease, background-color .18s ease;
}
.hd-15__burger:hover {
border-color: var(--accent);
background: rgba(34,224,208,.08);
}
.hd-15__bars {
display: grid;
gap: 4px;
inline-size: 1.4rem;
}
.hd-15__bars span {
display: block;
block-size: 2px;
background: var(--ink);
border-radius: 2px;
transition: translate .3s cubic-bezier(.5,-.35,.4,1.4), rotate .3s cubic-bezier(.5,-.35,.4,1.4), opacity .2s ease, scale .2s ease, background-color .2s ease;
}
.hd-15__burger-t {
font-family: var(--font-display);
font-size: .82rem;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: var(--muted);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b1 {
translate: 0 6px;
rotate: 45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b2 {
opacity: 0;
scale: .3 1;
}
.hd-15:has(#hd-15-open:checked) .hd-15__b3 {
translate: 0 -6px;
rotate: -45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:focus-visible) .hd-15__burger {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ── full-screen overlay ──────────────────────────────────────────── */
.hd-15__overlay {
position: fixed;
inset: 0;
z-index: 70;
display: grid;
align-items: center;
background: rgba(0,0,0,.94);
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: opacity .28s ease, visibility .28s allow-discrete;
}
@supports (backdrop-filter: blur(2px)) {
.hd-15__overlay {
background: rgba(0,0,0,.72);
backdrop-filter: blur(22px) saturate(120%);
}
}
.hd-15:has(#hd-15-open:checked) .hd-15__overlay {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.hd-15__close-all {
position: absolute;
inset: 0;
cursor: default;
}
.hd-15__overlay-in {
position: relative;
inline-size: 100%;
max-inline-size: 72rem;
margin-inline: auto;
display: grid;
grid-template-columns: minmax(0,1fr) 14rem;
gap: clamp(1.5rem,5vw,4rem);
align-items: end;
padding: clamp(2rem,8vh,5rem) clamp(1.25rem,5vw,3rem);
}
.hd-15__menu ul {
display: grid;
gap: .1rem;
}
.hd-15__link {
display: flex;
align-items: baseline;
gap: 1rem;
padding: .15rem 0;
font-family: var(--font-display);
font-size: var(--menu-size);
line-height: 1.05;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
color: var(--ink);
text-decoration: none;
transition: color .18s ease, translate .18s ease;
}
.hd-15__link:hover {
color: var(--accent);
translate: .6rem 0;
}
.hd-15__num {
font-family: var(--font-body);
font-size: .8rem;
font-weight: 600;
letter-spacing: .14em;
color: var(--muted);
flex: none;
}
.hd-15__meta {
display: grid;
gap: .25rem;
color: var(--muted);
font-size: .85rem;
}
.hd-15__meta-h {
font-size: .68rem;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--accent);
margin-top: .75rem;
}
.hd-15__meta-h:first-child {
margin-top: 0;
}
.hd-15__close {
position: absolute;
top: clamp(1rem,3vw,1.5rem);
inset-inline-end: clamp(1rem,4vw,2.5rem);
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 1px solid var(--line);
color: var(--ink);
cursor: pointer;
transition: border-color .18s ease, color .18s ease;
}
.hd-15__close svg {
inline-size: 1.3rem;
block-size: 1.3rem;
}
.hd-15__close:hover {
border-color: var(--accent);
color: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__link,
.hd-15:has(#hd-15-open:checked) .hd-15__meta {
animation: hd-15-in .45s cubic-bezier(.2,.8,.2,1) backwards;
animation-delay: calc(var(--i,1) * 55ms + 80ms);
}
@keyframes hd-15-in {
from {
opacity: 0;
translate: 0 1.4rem;
}
}
/* ── page body ────────────────────────────────────────────────────── */
.hd-15__main {
max-inline-size: 64rem;
margin-inline: auto;
padding: clamp(3rem,9vw,6rem) clamp(1.25rem,4vw,2.5rem) 5rem;
}
.hd-15__eyebrow {
font-size: .72rem;
font-weight: 700;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--accent);
}
.hd-15__main h1 {
font-family: var(--font-display);
font-size: clamp(2.2rem,8vw,4.4rem);
line-height: 1.02;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
margin-top: 1rem;
max-inline-size: 22ch;
text-wrap: balance;
}
.hd-15__lead {
margin-top: 1.2rem;
max-inline-size: 52ch;
color: var(--muted);
font-size: 1.02rem;
text-wrap: pretty;
}
.hd-15__work {
margin-top: clamp(2.5rem,7vw,4rem);
border-top: 1px solid var(--line);
}
.hd-15__work li {
display: grid;
grid-template-columns: 3rem minmax(0,1fr) 4rem;
align-items: center;
gap: 1rem;
padding: 1rem .25rem;
border-bottom: 1px solid var(--line);
}
.hd-15__work li:hover {
background: var(--surface);
}
.hd-15__w-n {
font-size: .75rem;
letter-spacing: .14em;
color: var(--muted);
}
.hd-15__w-t {
font-family: var(--font-display);
font-size: 1.25rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .02em;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__w-y {
font-size: .8rem;
color: var(--muted);
text-align: end;
font-variant-numeric: tabular-nums;
}
.hd-15__filler {
block-size: 40vh;
}
@media (max-width: 720px) {
.hd-15__tag {
display: none;
}
.hd-15__overlay-in {
grid-template-columns: minmax(0,1fr);
align-items: start;
}
.hd-15__meta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.hd-15 * {
animation-duration: 1ms !important;
transition-duration: 1ms !important;
}
}
@media (forced-colors: active) {
.hd-15__overlay {
background: Canvas;
}
.hd-15__burger,
.hd-15__close {
border: 1px solid CanvasText;
}
}
/* ── manual theme toggle — beats the OS default ──────────────────── */
.hd-15:has(#hd-15-light:checked) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* icon: shows the scheme the toggle will switch you to */
.hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: block;
}
@media (prefers-color-scheme: light) {
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* FLIP-BACK — light OS + checked toggle returns to the dark surface */
.hd-15:has(#hd-15-light:checked) {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
}
/* the icon always offers the scheme you are not in */
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__sun {
display: none;
}
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__moon {
display: block;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: block;
}
}
.hd-15[data-theme="light"] {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* ── theme toggle — visually hidden checkbox, zero JS ────────────── */
.hd-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__theme {
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 0;
border-radius: 999px;
background: transparent;
color: inherit;
cursor: pointer;
transition: background-color .18s ease;
}
.hd-15__theme svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.hd-15__theme:hover {
background: rgba(128,128,128,.16);
}
.hd-15:has(#hd-15-light:focus-visible) .hd-15__theme {
outline: 2px solid currentColor;
outline-offset: 2px;
}Here's a working CSS Header 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: Full Screen Overlay Hamburger Header
Source: https://codefronts.com/layouts/css-header-designs/full-screen-overlay-hamburger-header/
A header that opens into a full-screen navigation overlay with no JavaScript: a visually hidden checkbox, a label styled as the hamburger, and :has(:checked) on the root. The bars morph into an X with a spring curve, menu items stagger in on animation-delay, and the closed overlay is hidden with visibility so its links never sit in the tab order.
## HTML
```html
<div class="hd-15">
<a class="hd-15__skip" href="#hd-15-main">Skip to content</a>
<input class="hd-15__sr" type="checkbox" id="hd-15-open" aria-label="Open navigation menu">
<header class="hd-15__bar">
<a class="hd-15__brand" href="#hd-15-main">
<span class="hd-15__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" focusable="false"><path d="M12 3.5 20.5 12 12 20.5 3.5 12 12 3.5Z" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="2.6" fill="currentColor"/></svg>
</span>
<span class="hd-15__word">Vantage</span>
</a>
<p class="hd-15__tag">Studio for interface engineering</p>
<input class="hd-15__sr" type="checkbox" id="hd-15-light">
<label class="hd-15__theme" for="hd-15-light">
<svg class="hd-15__moon" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M20.5 14.4A8.4 8.4 0 0 1 9.6 3.5 8.6 8.6 0 1 0 20.5 14.4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
<svg class="hd-15__sun" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4.2" stroke="currentColor" stroke-width="1.8"/><path d="M12 2.8v2.1M12 19.1v2.1M2.8 12h2.1M19.1 12h2.1M5.5 5.5 7 7M17 17l1.5 1.5M18.5 5.5 17 7M7 17l-1.5 1.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Switch light or dark theme</span>
</label>
<label class="hd-15__burger" for="hd-15-open">
<span class="hd-15__bars" aria-hidden="true">
<span class="hd-15__b1"></span><span class="hd-15__b2"></span><span class="hd-15__b3"></span>
</span>
<span class="hd-15__burger-t" aria-hidden="true">Menu</span>
</label>
</header>
<div class="hd-15__overlay">
<label class="hd-15__close-all" for="hd-15-open" aria-label="Close navigation menu"></label>
<div class="hd-15__overlay-in">
<nav class="hd-15__menu" aria-label="Main">
<ul>
<li style="--i:1"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">01</span>Work</a></li>
<li style="--i:2"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">02</span>Services</a></li>
<li style="--i:3"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">03</span>Studio</a></li>
<li style="--i:4"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">04</span>Writing</a></li>
<li style="--i:5"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">05</span>Contact</a></li>
</ul>
</nav>
<div class="hd-15__meta" style="--i:6">
<p class="hd-15__meta-h">Studio</p>
<p>Unit 4, Ropewalk<br>Bristol BS1 6QT</p>
<p class="hd-15__meta-h">New work</p>
<p>hello@vantage.studio<br>+44 117 496 0142</p>
</div>
</div>
<label class="hd-15__close" for="hd-15-open">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Close navigation menu</span>
</label>
</div>
<main class="hd-15__main" id="hd-15-main">
<p class="hd-15__eyebrow">Selected work · 2026</p>
<h1>Interfaces that survive the second release.</h1>
<p class="hd-15__lead">Press the menu button — or tab to it and hit space. The bars morph, the overlay blurs the page and five links stagger in. Nothing here is JavaScript.</p>
<ul class="hd-15__work">
<li><span class="hd-15__w-n">01</span><span class="hd-15__w-t">Northwind — freight console</span><span class="hd-15__w-y">2026</span></li>
<li><span class="hd-15__w-n">02</span><span class="hd-15__w-t">Halcyon — design system</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">03</span><span class="hd-15__w-t">Meridian — docs platform</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">04</span><span class="hd-15__w-t">Foundry — asset pipeline</span><span class="hd-15__w-y">2024</span></li>
</ul>
<div class="hd-15__filler" aria-hidden="true"></div>
</main>
</div>
```
## CSS
```css
.hd-15 {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
--menu-size: clamp(2.1rem,9vw,4.6rem);
--font-display: "Avenir Next Condensed","Arial Narrow",system-ui,sans-serif;
--font-body: system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
display: block;
position: relative;
background: var(--bg);
color: var(--ink);
font-family: var(--font-body);
line-height: 1.55;
}
@supports (color: oklch(50% .1 200)) {
.hd-15 {
--surface: oklch(14% .006 200);
--ink: oklch(97% .006 200);
--muted: oklch(68% .015 200);
--accent: oklch(84% .14 185);
}
}
.hd-15 * {
box-sizing: border-box;
}
.hd-15 h1,
.hd-15 p,
.hd-15 ul {
margin: 0;
padding: 0;
}
.hd-15 ul {
list-style: none;
}
.hd-15 [hidden] {
display: none;
}
.hd-15 :focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.hd-15__sr,
.hd-15__vh {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__skip {
position: absolute;
inset-inline-start: 1rem;
top: -3rem;
z-index: 80;
padding: .55rem 1rem;
background: var(--accent);
color: var(--accent-ink);
font-size: .8rem;
font-weight: 700;
text-decoration: none;
transition: top .18s ease;
}
.hd-15__skip:focus-visible {
top: 1rem;
}
/* ── header: no chrome, type only ─────────────────────────────────── */
.hd-15__bar {
position: sticky;
top: 0;
z-index: 60;
display: flex;
align-items: center;
gap: 1.5rem;
padding: clamp(1rem,3vw,1.5rem) clamp(1rem,4vw,2.5rem);
background: color-mix(in srgb, var(--bg) 78%, transparent);
backdrop-filter: blur(10px);
}
.hd-15__brand {
display: inline-flex;
align-items: center;
gap: .6rem;
color: var(--ink);
text-decoration: none;
min-inline-size: 0;
}
.hd-15__mark {
display: grid;
place-items: center;
inline-size: 1.9rem;
block-size: 1.9rem;
color: var(--accent);
flex: none;
}
.hd-15__mark svg {
inline-size: 1.9rem;
block-size: 1.9rem;
}
.hd-15__word {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__tag {
font-size: .72rem;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--muted);
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__burger {
display: inline-flex;
align-items: center;
gap: .6rem;
margin-inline-start: auto;
min-block-size: 2.75rem;
padding: .5rem .75rem;
border: 1px solid var(--line);
cursor: pointer;
transition: border-color .18s ease, background-color .18s ease;
}
.hd-15__burger:hover {
border-color: var(--accent);
background: rgba(34,224,208,.08);
}
.hd-15__bars {
display: grid;
gap: 4px;
inline-size: 1.4rem;
}
.hd-15__bars span {
display: block;
block-size: 2px;
background: var(--ink);
border-radius: 2px;
transition: translate .3s cubic-bezier(.5,-.35,.4,1.4), rotate .3s cubic-bezier(.5,-.35,.4,1.4), opacity .2s ease, scale .2s ease, background-color .2s ease;
}
.hd-15__burger-t {
font-family: var(--font-display);
font-size: .82rem;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: var(--muted);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b1 {
translate: 0 6px;
rotate: 45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b2 {
opacity: 0;
scale: .3 1;
}
.hd-15:has(#hd-15-open:checked) .hd-15__b3 {
translate: 0 -6px;
rotate: -45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:focus-visible) .hd-15__burger {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ── full-screen overlay ──────────────────────────────────────────── */
.hd-15__overlay {
position: fixed;
inset: 0;
z-index: 70;
display: grid;
align-items: center;
background: rgba(0,0,0,.94);
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: opacity .28s ease, visibility .28s allow-discrete;
}
@supports (backdrop-filter: blur(2px)) {
.hd-15__overlay {
background: rgba(0,0,0,.72);
backdrop-filter: blur(22px) saturate(120%);
}
}
.hd-15:has(#hd-15-open:checked) .hd-15__overlay {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.hd-15__close-all {
position: absolute;
inset: 0;
cursor: default;
}
.hd-15__overlay-in {
position: relative;
inline-size: 100%;
max-inline-size: 72rem;
margin-inline: auto;
display: grid;
grid-template-columns: minmax(0,1fr) 14rem;
gap: clamp(1.5rem,5vw,4rem);
align-items: end;
padding: clamp(2rem,8vh,5rem) clamp(1.25rem,5vw,3rem);
}
.hd-15__menu ul {
display: grid;
gap: .1rem;
}
.hd-15__link {
display: flex;
align-items: baseline;
gap: 1rem;
padding: .15rem 0;
font-family: var(--font-display);
font-size: var(--menu-size);
line-height: 1.05;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
color: var(--ink);
text-decoration: none;
transition: color .18s ease, translate .18s ease;
}
.hd-15__link:hover {
color: var(--accent);
translate: .6rem 0;
}
.hd-15__num {
font-family: var(--font-body);
font-size: .8rem;
font-weight: 600;
letter-spacing: .14em;
color: var(--muted);
flex: none;
}
.hd-15__meta {
display: grid;
gap: .25rem;
color: var(--muted);
font-size: .85rem;
}
.hd-15__meta-h {
font-size: .68rem;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--accent);
margin-top: .75rem;
}
.hd-15__meta-h:first-child {
margin-top: 0;
}
.hd-15__close {
position: absolute;
top: clamp(1rem,3vw,1.5rem);
inset-inline-end: clamp(1rem,4vw,2.5rem);
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 1px solid var(--line);
color: var(--ink);
cursor: pointer;
transition: border-color .18s ease, color .18s ease;
}
.hd-15__close svg {
inline-size: 1.3rem;
block-size: 1.3rem;
}
.hd-15__close:hover {
border-color: var(--accent);
color: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__link,
.hd-15:has(#hd-15-open:checked) .hd-15__meta {
animation: hd-15-in .45s cubic-bezier(.2,.8,.2,1) backwards;
animation-delay: calc(var(--i,1) * 55ms + 80ms);
}
@keyframes hd-15-in {
from {
opacity: 0;
translate: 0 1.4rem;
}
}
/* ── page body ────────────────────────────────────────────────────── */
.hd-15__main {
max-inline-size: 64rem;
margin-inline: auto;
padding: clamp(3rem,9vw,6rem) clamp(1.25rem,4vw,2.5rem) 5rem;
}
.hd-15__eyebrow {
font-size: .72rem;
font-weight: 700;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--accent);
}
.hd-15__main h1 {
font-family: var(--font-display);
font-size: clamp(2.2rem,8vw,4.4rem);
line-height: 1.02;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
margin-top: 1rem;
max-inline-size: 22ch;
text-wrap: balance;
}
.hd-15__lead {
margin-top: 1.2rem;
max-inline-size: 52ch;
color: var(--muted);
font-size: 1.02rem;
text-wrap: pretty;
}
.hd-15__work {
margin-top: clamp(2.5rem,7vw,4rem);
border-top: 1px solid var(--line);
}
.hd-15__work li {
display: grid;
grid-template-columns: 3rem minmax(0,1fr) 4rem;
align-items: center;
gap: 1rem;
padding: 1rem .25rem;
border-bottom: 1px solid var(--line);
}
.hd-15__work li:hover {
background: var(--surface);
}
.hd-15__w-n {
font-size: .75rem;
letter-spacing: .14em;
color: var(--muted);
}
.hd-15__w-t {
font-family: var(--font-display);
font-size: 1.25rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .02em;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__w-y {
font-size: .8rem;
color: var(--muted);
text-align: end;
font-variant-numeric: tabular-nums;
}
.hd-15__filler {
block-size: 40vh;
}
@media (max-width: 720px) {
.hd-15__tag {
display: none;
}
.hd-15__overlay-in {
grid-template-columns: minmax(0,1fr);
align-items: start;
}
.hd-15__meta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.hd-15 * {
animation-duration: 1ms !important;
transition-duration: 1ms !important;
}
}
@media (forced-colors: active) {
.hd-15__overlay {
background: Canvas;
}
.hd-15__burger,
.hd-15__close {
border: 1px solid CanvasText;
}
}
/* ── manual theme toggle — beats the OS default ──────────────────── */
.hd-15:has(#hd-15-light:checked) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* icon: shows the scheme the toggle will switch you to */
.hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: block;
}
@media (prefers-color-scheme: light) {
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* FLIP-BACK — light OS + checked toggle returns to the dark surface */
.hd-15:has(#hd-15-light:checked) {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
}
/* the icon always offers the scheme you are not in */
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__sun {
display: none;
}
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__moon {
display: block;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: block;
}
}
.hd-15[data-theme="light"] {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* ── theme toggle — visually hidden checkbox, zero JS ────────────── */
.hd-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__theme {
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 0;
border-radius: 999px;
background: transparent;
color: inherit;
cursor: pointer;
transition: background-color .18s ease;
}
.hd-15__theme svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.hd-15__theme:hover {
background: rgba(128,128,128,.16);
}
.hd-15:has(#hd-15-light:focus-visible) .hd-15__theme {
outline: 2px solid currentColor;
outline-offset: 2px;
}
```Here's a working CSS Header 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: Full Screen Overlay Hamburger Header
Source: https://codefronts.com/layouts/css-header-designs/full-screen-overlay-hamburger-header/
A header that opens into a full-screen navigation overlay with no JavaScript: a visually hidden checkbox, a label styled as the hamburger, and :has(:checked) on the root. The bars morph into an X with a spring curve, menu items stagger in on animation-delay, and the closed overlay is hidden with visibility so its links never sit in the tab order.
## HTML
```html
<div class="hd-15">
<a class="hd-15__skip" href="#hd-15-main">Skip to content</a>
<input class="hd-15__sr" type="checkbox" id="hd-15-open" aria-label="Open navigation menu">
<header class="hd-15__bar">
<a class="hd-15__brand" href="#hd-15-main">
<span class="hd-15__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" focusable="false"><path d="M12 3.5 20.5 12 12 20.5 3.5 12 12 3.5Z" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="2.6" fill="currentColor"/></svg>
</span>
<span class="hd-15__word">Vantage</span>
</a>
<p class="hd-15__tag">Studio for interface engineering</p>
<input class="hd-15__sr" type="checkbox" id="hd-15-light">
<label class="hd-15__theme" for="hd-15-light">
<svg class="hd-15__moon" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M20.5 14.4A8.4 8.4 0 0 1 9.6 3.5 8.6 8.6 0 1 0 20.5 14.4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
<svg class="hd-15__sun" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4.2" stroke="currentColor" stroke-width="1.8"/><path d="M12 2.8v2.1M12 19.1v2.1M2.8 12h2.1M19.1 12h2.1M5.5 5.5 7 7M17 17l1.5 1.5M18.5 5.5 17 7M7 17l-1.5 1.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Switch light or dark theme</span>
</label>
<label class="hd-15__burger" for="hd-15-open">
<span class="hd-15__bars" aria-hidden="true">
<span class="hd-15__b1"></span><span class="hd-15__b2"></span><span class="hd-15__b3"></span>
</span>
<span class="hd-15__burger-t" aria-hidden="true">Menu</span>
</label>
</header>
<div class="hd-15__overlay">
<label class="hd-15__close-all" for="hd-15-open" aria-label="Close navigation menu"></label>
<div class="hd-15__overlay-in">
<nav class="hd-15__menu" aria-label="Main">
<ul>
<li style="--i:1"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">01</span>Work</a></li>
<li style="--i:2"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">02</span>Services</a></li>
<li style="--i:3"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">03</span>Studio</a></li>
<li style="--i:4"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">04</span>Writing</a></li>
<li style="--i:5"><a class="hd-15__link" href="#hd-15-main"><span class="hd-15__num">05</span>Contact</a></li>
</ul>
</nav>
<div class="hd-15__meta" style="--i:6">
<p class="hd-15__meta-h">Studio</p>
<p>Unit 4, Ropewalk<br>Bristol BS1 6QT</p>
<p class="hd-15__meta-h">New work</p>
<p>hello@vantage.studio<br>+44 117 496 0142</p>
</div>
</div>
<label class="hd-15__close" for="hd-15-open">
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span class="hd-15__vh">Close navigation menu</span>
</label>
</div>
<main class="hd-15__main" id="hd-15-main">
<p class="hd-15__eyebrow">Selected work · 2026</p>
<h1>Interfaces that survive the second release.</h1>
<p class="hd-15__lead">Press the menu button — or tab to it and hit space. The bars morph, the overlay blurs the page and five links stagger in. Nothing here is JavaScript.</p>
<ul class="hd-15__work">
<li><span class="hd-15__w-n">01</span><span class="hd-15__w-t">Northwind — freight console</span><span class="hd-15__w-y">2026</span></li>
<li><span class="hd-15__w-n">02</span><span class="hd-15__w-t">Halcyon — design system</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">03</span><span class="hd-15__w-t">Meridian — docs platform</span><span class="hd-15__w-y">2025</span></li>
<li><span class="hd-15__w-n">04</span><span class="hd-15__w-t">Foundry — asset pipeline</span><span class="hd-15__w-y">2024</span></li>
</ul>
<div class="hd-15__filler" aria-hidden="true"></div>
</main>
</div>
```
## CSS
```css
.hd-15 {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
--menu-size: clamp(2.1rem,9vw,4.6rem);
--font-display: "Avenir Next Condensed","Arial Narrow",system-ui,sans-serif;
--font-body: system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
display: block;
position: relative;
background: var(--bg);
color: var(--ink);
font-family: var(--font-body);
line-height: 1.55;
}
@supports (color: oklch(50% .1 200)) {
.hd-15 {
--surface: oklch(14% .006 200);
--ink: oklch(97% .006 200);
--muted: oklch(68% .015 200);
--accent: oklch(84% .14 185);
}
}
.hd-15 * {
box-sizing: border-box;
}
.hd-15 h1,
.hd-15 p,
.hd-15 ul {
margin: 0;
padding: 0;
}
.hd-15 ul {
list-style: none;
}
.hd-15 [hidden] {
display: none;
}
.hd-15 :focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.hd-15__sr,
.hd-15__vh {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__skip {
position: absolute;
inset-inline-start: 1rem;
top: -3rem;
z-index: 80;
padding: .55rem 1rem;
background: var(--accent);
color: var(--accent-ink);
font-size: .8rem;
font-weight: 700;
text-decoration: none;
transition: top .18s ease;
}
.hd-15__skip:focus-visible {
top: 1rem;
}
/* ── header: no chrome, type only ─────────────────────────────────── */
.hd-15__bar {
position: sticky;
top: 0;
z-index: 60;
display: flex;
align-items: center;
gap: 1.5rem;
padding: clamp(1rem,3vw,1.5rem) clamp(1rem,4vw,2.5rem);
background: color-mix(in srgb, var(--bg) 78%, transparent);
backdrop-filter: blur(10px);
}
.hd-15__brand {
display: inline-flex;
align-items: center;
gap: .6rem;
color: var(--ink);
text-decoration: none;
min-inline-size: 0;
}
.hd-15__mark {
display: grid;
place-items: center;
inline-size: 1.9rem;
block-size: 1.9rem;
color: var(--accent);
flex: none;
}
.hd-15__mark svg {
inline-size: 1.9rem;
block-size: 1.9rem;
}
.hd-15__word {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__tag {
font-size: .72rem;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--muted);
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__burger {
display: inline-flex;
align-items: center;
gap: .6rem;
margin-inline-start: auto;
min-block-size: 2.75rem;
padding: .5rem .75rem;
border: 1px solid var(--line);
cursor: pointer;
transition: border-color .18s ease, background-color .18s ease;
}
.hd-15__burger:hover {
border-color: var(--accent);
background: rgba(34,224,208,.08);
}
.hd-15__bars {
display: grid;
gap: 4px;
inline-size: 1.4rem;
}
.hd-15__bars span {
display: block;
block-size: 2px;
background: var(--ink);
border-radius: 2px;
transition: translate .3s cubic-bezier(.5,-.35,.4,1.4), rotate .3s cubic-bezier(.5,-.35,.4,1.4), opacity .2s ease, scale .2s ease, background-color .2s ease;
}
.hd-15__burger-t {
font-family: var(--font-display);
font-size: .82rem;
font-weight: 700;
letter-spacing: .18em;
text-transform: uppercase;
color: var(--muted);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b1 {
translate: 0 6px;
rotate: 45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__b2 {
opacity: 0;
scale: .3 1;
}
.hd-15:has(#hd-15-open:checked) .hd-15__b3 {
translate: 0 -6px;
rotate: -45deg;
background: var(--accent);
}
.hd-15:has(#hd-15-open:focus-visible) .hd-15__burger {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ── full-screen overlay ──────────────────────────────────────────── */
.hd-15__overlay {
position: fixed;
inset: 0;
z-index: 70;
display: grid;
align-items: center;
background: rgba(0,0,0,.94);
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: opacity .28s ease, visibility .28s allow-discrete;
}
@supports (backdrop-filter: blur(2px)) {
.hd-15__overlay {
background: rgba(0,0,0,.72);
backdrop-filter: blur(22px) saturate(120%);
}
}
.hd-15:has(#hd-15-open:checked) .hd-15__overlay {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.hd-15__close-all {
position: absolute;
inset: 0;
cursor: default;
}
.hd-15__overlay-in {
position: relative;
inline-size: 100%;
max-inline-size: 72rem;
margin-inline: auto;
display: grid;
grid-template-columns: minmax(0,1fr) 14rem;
gap: clamp(1.5rem,5vw,4rem);
align-items: end;
padding: clamp(2rem,8vh,5rem) clamp(1.25rem,5vw,3rem);
}
.hd-15__menu ul {
display: grid;
gap: .1rem;
}
.hd-15__link {
display: flex;
align-items: baseline;
gap: 1rem;
padding: .15rem 0;
font-family: var(--font-display);
font-size: var(--menu-size);
line-height: 1.05;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
color: var(--ink);
text-decoration: none;
transition: color .18s ease, translate .18s ease;
}
.hd-15__link:hover {
color: var(--accent);
translate: .6rem 0;
}
.hd-15__num {
font-family: var(--font-body);
font-size: .8rem;
font-weight: 600;
letter-spacing: .14em;
color: var(--muted);
flex: none;
}
.hd-15__meta {
display: grid;
gap: .25rem;
color: var(--muted);
font-size: .85rem;
}
.hd-15__meta-h {
font-size: .68rem;
font-weight: 700;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--accent);
margin-top: .75rem;
}
.hd-15__meta-h:first-child {
margin-top: 0;
}
.hd-15__close {
position: absolute;
top: clamp(1rem,3vw,1.5rem);
inset-inline-end: clamp(1rem,4vw,2.5rem);
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 1px solid var(--line);
color: var(--ink);
cursor: pointer;
transition: border-color .18s ease, color .18s ease;
}
.hd-15__close svg {
inline-size: 1.3rem;
block-size: 1.3rem;
}
.hd-15__close:hover {
border-color: var(--accent);
color: var(--accent);
}
.hd-15:has(#hd-15-open:checked) .hd-15__link,
.hd-15:has(#hd-15-open:checked) .hd-15__meta {
animation: hd-15-in .45s cubic-bezier(.2,.8,.2,1) backwards;
animation-delay: calc(var(--i,1) * 55ms + 80ms);
}
@keyframes hd-15-in {
from {
opacity: 0;
translate: 0 1.4rem;
}
}
/* ── page body ────────────────────────────────────────────────────── */
.hd-15__main {
max-inline-size: 64rem;
margin-inline: auto;
padding: clamp(3rem,9vw,6rem) clamp(1.25rem,4vw,2.5rem) 5rem;
}
.hd-15__eyebrow {
font-size: .72rem;
font-weight: 700;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--accent);
}
.hd-15__main h1 {
font-family: var(--font-display);
font-size: clamp(2.2rem,8vw,4.4rem);
line-height: 1.02;
font-weight: 700;
letter-spacing: -.01em;
text-transform: uppercase;
margin-top: 1rem;
max-inline-size: 22ch;
text-wrap: balance;
}
.hd-15__lead {
margin-top: 1.2rem;
max-inline-size: 52ch;
color: var(--muted);
font-size: 1.02rem;
text-wrap: pretty;
}
.hd-15__work {
margin-top: clamp(2.5rem,7vw,4rem);
border-top: 1px solid var(--line);
}
.hd-15__work li {
display: grid;
grid-template-columns: 3rem minmax(0,1fr) 4rem;
align-items: center;
gap: 1rem;
padding: 1rem .25rem;
border-bottom: 1px solid var(--line);
}
.hd-15__work li:hover {
background: var(--surface);
}
.hd-15__w-n {
font-size: .75rem;
letter-spacing: .14em;
color: var(--muted);
}
.hd-15__w-t {
font-family: var(--font-display);
font-size: 1.25rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .02em;
min-inline-size: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.hd-15__w-y {
font-size: .8rem;
color: var(--muted);
text-align: end;
font-variant-numeric: tabular-nums;
}
.hd-15__filler {
block-size: 40vh;
}
@media (max-width: 720px) {
.hd-15__tag {
display: none;
}
.hd-15__overlay-in {
grid-template-columns: minmax(0,1fr);
align-items: start;
}
.hd-15__meta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.hd-15 * {
animation-duration: 1ms !important;
transition-duration: 1ms !important;
}
}
@media (forced-colors: active) {
.hd-15__overlay {
background: Canvas;
}
.hd-15__burger,
.hd-15__close {
border: 1px solid CanvasText;
}
}
/* ── manual theme toggle — beats the OS default ──────────────────── */
.hd-15:has(#hd-15-light:checked) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* icon: shows the scheme the toggle will switch you to */
.hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: block;
}
@media (prefers-color-scheme: light) {
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* FLIP-BACK — light OS + checked toggle returns to the dark surface */
.hd-15:has(#hd-15-light:checked) {
--bg: #000000;
--surface: #0b0d0f;
--ink: #f4f7f8;
--muted: #8c9599;
--line: rgba(244,247,248,.14);
--accent: #22e0d0;
--accent-ink: #00201d;
}
/* the icon always offers the scheme you are not in */
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__sun {
display: none;
}
.hd-15:not([data-theme="dark"]):not(:has(#hd-15-light:checked)) .hd-15__moon {
display: block;
}
.hd-15:has(#hd-15-light:checked) .hd-15__moon {
display: none;
}
.hd-15:has(#hd-15-light:checked) .hd-15__sun {
display: block;
}
}
.hd-15[data-theme="light"] {
--bg: #f6f8f8;
--surface: #ffffff;
--ink: #0b0d0f;
--muted: #5b6568;
--line: rgba(11,13,15,.14);
--accent: #0f8f85;
--accent-ink: #ffffff;
}
/* ── theme toggle — visually hidden checkbox, zero JS ────────────── */
.hd-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.hd-15__theme {
display: grid;
place-items: center;
inline-size: 2.75rem;
block-size: 2.75rem;
border: 0;
border-radius: 999px;
background: transparent;
color: inherit;
cursor: pointer;
transition: background-color .18s ease;
}
.hd-15__theme svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.hd-15__theme:hover {
background: rgba(128,128,128,.16);
}
.hd-15:has(#hd-15-light:focus-visible) .hd-15__theme {
outline: 2px solid currentColor;
outline-offset: 2px;
}
```How this works
The checkbox stays focusable on purpose. display:none on the input would remove it from the tab order and break keyboard access — the most common flaw in checkbox-hack menus. Clipping it instead keeps it operable with Space while the label carries the visuals:
.hd-15__sr{position:absolute; inline-size:1px; block-size:1px;
overflow:hidden; clip-path:inset(50%);} /* focusable, invisible */
.hd-15:has(#hd-15-open:checked) .hd-15__overlay{visibility:visible; opacity:1;}The morph is two spans and four declarations. The middle bar fades; the outer bars translate to the centre and rotate. Using a spring-ish cubic-bezier gives the X a slight overshoot, which is what makes the interaction feel physical rather than mechanical:
.hd-15:has(:checked) .hd-15__b1{translate:0 6px; rotate:45deg;}
.hd-15:has(:checked) .hd-15__b2{opacity:0; scale:.4 1;}
.hd-15:has(:checked) .hd-15__b3{translate:0 -6px; rotate:-45deg;}
.hd-15__bar span{transition:translate .3s cubic-bezier(.5,-.4,.4,1.4), rotate .3s;}Stagger with one custom property. Each list item declares style="--i:3" and the animation delay is computed from it, so adding a link needs no new CSS. The entrance runs on opacity and translate only, so eight items animating at once still hold 60 fps on a mid-range phone:
.hd-15:has(:checked) .hd-15__link{
animation:hd-15-in .45s cubic-bezier(.2,.8,.2,1) backwards;
animation-delay:calc(var(--i) * 55ms + 80ms);
}The trap: an overlay that is invisible but still there. If you hide it with opacity:0 alone, its links stay clickable and focusable across the whole viewport — the page appears frozen. Hide with visibility (transitioned with allow-discrete), keep pointer-events:none as a belt-and-braces measure, and ship the [hidden]{display:none} guard so a stray author display:flex cannot re-open it.
Make it yours
- Change the stagger rhythm with the
55msstep inanimation-delay; 40-70 ms feels lively, above 120 ms it drags. - Swap the cyan accent through
--accent; the hamburger, hovers and the meta column follow. - Set the menu type scale with
--menu-size; it is aclamp(), so one edit rescales every breakpoint. - Turn the overlay into a panel by constraining
inline-sizeand addinginset-inline-start:auto. - Add a secondary column (contact details, social links) inside the overlay grid — it is a two-column grid above 720 px.
- Keep the overlay open on desktop instead by moving the nav out of the overlay above a breakpoint with
display:contents.
Gotchas — read before shipping
display:noneon the checkbox removes it from the tab order — the menu then cannot be opened by keyboard at all. Clip it instead.- An overlay hidden with only
opacity:0intercepts every click on the page; hide withvisibilityand keep the[hidden]guard rule. - Pure CSS cannot listen for Esc. Provide a real close control (this demo uses a full-bleed close label plus a visible X) so users are never trapped.
- Staggering with
transition-delayinstead ofanimation-delaymakes the items animate out in reverse on close, which reads as sluggish; keyframes withbackwardsfill avoid it.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 117+ | 17.4+ | 129+ | 117+ |
:has() (Chrome 105 / Safari 15.4 / Firefox 121) drives the whole demo. transition-behavior: allow-discrete (Chrome 117 / Safari 17.4 / Firefox 129) smooths the close; without it the overlay disappears instantly. backdrop-filter degrades to the solid background declared first.