25 CSS Sticky Navigation05 / 25
Floating Glass Pill Sticky Navbar (Rounded, Backdrop Blur, Elevation)
The detached pill header used across modern product and portfolio sites: lifted away from the viewport edge, rounded to a full radius, and frosted so the page reads through it as it scrolls past. The demo covers the two things that make or break the effect — a genuinely layered rim light instead of a flat border, and a solid fallback where backdrop blur is unavailable.
Published
The code
<section class="sn-05" aria-label="Floating glass pill sticky navbar demo">
<header class="sn-05__pill">
<a class="sn-05__brand" href="#sn-05-s1"><span class="sn-05__logo" aria-hidden="true"></span>Lumen</a>
<nav class="sn-05__nav" aria-label="Primary">
<a class="sn-05__link" href="#sn-05-s1" aria-current="page">Work</a>
<a class="sn-05__link" href="#sn-05-s2">Studio</a>
<a class="sn-05__link" href="#sn-05-s3">Journal</a>
</nav>
<a class="sn-05__cta" href="#sn-05-s3">Contact</a>
</header>
<div class="sn-05__hero">
<img class="sn-05__img" src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=1400&auto=format&fit=crop" alt="Abstract flowing colour gradient" width="1400" height="900" loading="lazy" decoding="async">
<div class="sn-05__herotext">
<p class="sn-05__kicker">Glassmorphism</p>
<h2 class="sn-05__title">Chrome that floats</h2>
<p class="sn-05__sub">Scroll — the artwork passes underneath and the pill stays legible the whole way.</p>
</div>
</div>
<main class="sn-05__main">
<section class="sn-05__sec" id="sn-05-s1">
<h3 class="sn-05__h">Blur plus saturation</h3>
<p class="sn-05__p">Blur alone greys out whatever is behind it. <code>saturate(1.8)</code> restores the colour bleeding through, and that is the half of the recipe most tutorials leave out.</p>
</section>
<section class="sn-05__sec" id="sn-05-s2">
<h3 class="sn-05__h">Rim light, not a border</h3>
<p class="sn-05__p">A bright <code>inset 0 1px 0</code> on the top edge and a darker one below make the pill read as a solid piece of glass catching light.</p>
</section>
<section class="sn-05__sec" id="sn-05-s3">
<h3 class="sn-05__h">Legible in every engine</h3>
<p class="sn-05__p">An <code>@supports not (backdrop-filter: blur(1px))</code> block swaps in an opaque surface, so the labels never fall below contrast where blur is unavailable.</p>
</section>
</main>
<footer class="sn-05__pagefoot">
<p class="sn-05__pagefootin">Sticky navigation pattern 05 of 25 · codefronts.com</p>
</footer>
</section><section class="sn-05" aria-label="Floating glass pill sticky navbar demo">
<header class="sn-05__pill">
<a class="sn-05__brand" href="#sn-05-s1"><span class="sn-05__logo" aria-hidden="true"></span>Lumen</a>
<nav class="sn-05__nav" aria-label="Primary">
<a class="sn-05__link" href="#sn-05-s1" aria-current="page">Work</a>
<a class="sn-05__link" href="#sn-05-s2">Studio</a>
<a class="sn-05__link" href="#sn-05-s3">Journal</a>
</nav>
<a class="sn-05__cta" href="#sn-05-s3">Contact</a>
</header>
<div class="sn-05__hero">
<img class="sn-05__img" src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=1400&auto=format&fit=crop" alt="Abstract flowing colour gradient" width="1400" height="900" loading="lazy" decoding="async">
<div class="sn-05__herotext">
<p class="sn-05__kicker">Glassmorphism</p>
<h2 class="sn-05__title">Chrome that floats</h2>
<p class="sn-05__sub">Scroll — the artwork passes underneath and the pill stays legible the whole way.</p>
</div>
</div>
<main class="sn-05__main">
<section class="sn-05__sec" id="sn-05-s1">
<h3 class="sn-05__h">Blur plus saturation</h3>
<p class="sn-05__p">Blur alone greys out whatever is behind it. <code>saturate(1.8)</code> restores the colour bleeding through, and that is the half of the recipe most tutorials leave out.</p>
</section>
<section class="sn-05__sec" id="sn-05-s2">
<h3 class="sn-05__h">Rim light, not a border</h3>
<p class="sn-05__p">A bright <code>inset 0 1px 0</code> on the top edge and a darker one below make the pill read as a solid piece of glass catching light.</p>
</section>
<section class="sn-05__sec" id="sn-05-s3">
<h3 class="sn-05__h">Legible in every engine</h3>
<p class="sn-05__p">An <code>@supports not (backdrop-filter: blur(1px))</code> block swaps in an opaque surface, so the labels never fall below contrast where blur is unavailable.</p>
</section>
</main>
<footer class="sn-05__pagefoot">
<p class="sn-05__pagefootin">Sticky navigation pattern 05 of 25 · codefronts.com</p>
</footer>
</section>.sn-05 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--sn-05-bg);
--sn-05-bg: oklch(0.17 0.03 285);
--sn-05-glass: oklch(0.28 0.04 285);
--sn-05-ink: oklch(0.98 0.005 285);
--sn-05-mut: oklch(0.8 0.02 285);
--sn-05-acc: oklch(0.8 0.15 330);
--sn-05-line: oklch(1 0 0/.16);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--sn-05-ink);
-webkit-font-smoothing: antialiased;
}
.sn-05 *,
.sn-05 *::before,
.sn-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sn-05__pill {
position: sticky;
top: 14px;
z-index: 20;
inline-size: min(100% - 28px,720px);
margin-inline: auto;
display: flex;
align-items: center;
gap: clamp(6px,1.6vw,18px);
min-height: 56px;
padding: 0 8px 0 18px;
border-radius: 999px;
border: 1px solid var(--sn-05-line);
background: color-mix(in oklch,var(--sn-05-glass) 58%,transparent);
backdrop-filter: blur(20px) saturate(1.8);
-webkit-backdrop-filter: blur(20px) saturate(1.8);
box-shadow: 0 18px 40px -18px oklch(0 0 0/.6),inset 0 1px 0 oklch(1 0 0/.22),inset 0 -1px 0 oklch(0 0 0/.28);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.sn-05__pill {
background: oklch(0.28 0.04 285);
}
}
.sn-05__brand {
display: flex;
align-items: center;
gap: 9px;
font-size: 15px;
font-weight: 700;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
white-space: nowrap;
}
.sn-05__logo {
width: 16px;
height: 16px;
border-radius: 50%;
background: conic-gradient(from 210deg,var(--sn-05-acc),oklch(0.85 0.14 200),var(--sn-05-acc));
box-shadow: 0 0 14px -2px var(--sn-05-acc);
}
.sn-05__nav {
display: flex;
align-items: center;
gap: 2px;
margin-inline-start: auto;
}
.sn-05__link {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 13px;
border-radius: 99px;
font-size: 13.6px;
font-weight: 600;
color: var(--sn-05-mut);
text-decoration: none;
transition: color .2s ease,background .2s ease;
}
.sn-05__link:hover {
color: var(--sn-05-ink);
background: oklch(1 0 0/.1);
}
.sn-05__link[aria-current="page"] {
color: var(--sn-05-ink);
background: oklch(1 0 0/.14);
}
.sn-05__cta {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 18px;
border-radius: 99px;
font-size: 13.4px;
font-weight: 670;
color: oklch(0.17 0.03 285);
background: var(--sn-05-ink);
text-decoration: none;
white-space: nowrap;
transition: transform .2s ease,background .2s ease;
}
.sn-05__cta:hover {
transform: translateY(-1px);
background: var(--sn-05-acc);
}
.sn-05__link:focus-visible,
.sn-05__cta:focus-visible,
.sn-05__brand:focus-visible {
outline: 2px solid var(--sn-05-acc);
outline-offset: 2px;
}
.sn-05__hero {
position: relative;
margin-block-start: -70px;
height: min(52svh,420px);
display: grid;
}
.sn-05__img {
grid-area: 1/1;
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(140deg,oklch(0.45 0.18 320),oklch(0.35 0.14 260));
}
.sn-05__herotext {
grid-area: 1/1;
align-self: end;
display: grid;
gap: 8px;
padding: clamp(20px,4vw,40px);
background: linear-gradient(to top,oklch(0.17 0.03 285/.92),transparent);
}
.sn-05__kicker {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--sn-05-acc);
}
.sn-05__title {
font-size: clamp(26px,5vw,44px);
line-height: 1.02;
letter-spacing: -.035em;
font-weight: 720;
text-wrap: balance;
}
.sn-05__sub {
max-width: 46ch;
font-size: 14.5px;
line-height: 1.6;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__main {
display: grid;
}
.sn-05__sec {
scroll-margin-top: 82px;
display: grid;
gap: 10px;
align-content: center;
min-height: 66svh;
padding: clamp(24px,4vw,46px);
border-top: 1px solid oklch(1 0 0/.07);
}
.sn-05__sec:nth-child(even) {
background: oklch(1 0 0/.03);
}
.sn-05__h {
font-size: clamp(19px,2.6vw,26px);
line-height: 1.16;
letter-spacing: -.025em;
font-weight: 690;
text-wrap: balance;
}
.sn-05__p {
max-width: 52ch;
font-size: 14.8px;
line-height: 1.64;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__p code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .85em;
background: oklch(1 0 0/.1);
padding: 2px 6px;
border-radius: 5px;
}
@media (max-width: 560px) {
.sn-05__pill {
padding-inline: 14px 6px;
}
.sn-05__link {
padding: 0 10px;
font-size: 12.8px;
}
.sn-05__cta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.sn-05 * {
transition-duration: .01ms !important;
}
}
/* ── full-page mode: the demo IS the document, so sticky pins against the real viewport ── */
:root:has(.sn-05) {
scroll-behavior: smooth;
scroll-padding-top: 82px;
}
@media (prefers-reduced-motion: reduce) {
:root:has(.sn-05) {
scroll-behavior: auto;
}
}
.sn-05__bar,
.sn-05__barin {
padding-inline: max(clamp(16px,3vw,26px),calc((100% - 1280px)/2));
}
.sn-05__sec {
padding-inline: max(clamp(22px,5vw,44px),calc((100% - 1120px)/2));
}
.sn-05__pagefoot {
display: grid;
place-items: center;
padding: clamp(44px,9vh,110px) 24px;
border-top: 1px solid var(--sn-05-line);
}
.sn-05__pagefootin {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .06em;
color: var(--sn-05-mut);
text-align: center;
}
.sn-05__intro-title,
.sn-05__intro-sub {
text-wrap: balance;
}.sn-05 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--sn-05-bg);
--sn-05-bg: oklch(0.17 0.03 285);
--sn-05-glass: oklch(0.28 0.04 285);
--sn-05-ink: oklch(0.98 0.005 285);
--sn-05-mut: oklch(0.8 0.02 285);
--sn-05-acc: oklch(0.8 0.15 330);
--sn-05-line: oklch(1 0 0/.16);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--sn-05-ink);
-webkit-font-smoothing: antialiased;
}
.sn-05 *,
.sn-05 *::before,
.sn-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sn-05__pill {
position: sticky;
top: 14px;
z-index: 20;
inline-size: min(100% - 28px,720px);
margin-inline: auto;
display: flex;
align-items: center;
gap: clamp(6px,1.6vw,18px);
min-height: 56px;
padding: 0 8px 0 18px;
border-radius: 999px;
border: 1px solid var(--sn-05-line);
background: color-mix(in oklch,var(--sn-05-glass) 58%,transparent);
backdrop-filter: blur(20px) saturate(1.8);
-webkit-backdrop-filter: blur(20px) saturate(1.8);
box-shadow: 0 18px 40px -18px oklch(0 0 0/.6),inset 0 1px 0 oklch(1 0 0/.22),inset 0 -1px 0 oklch(0 0 0/.28);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.sn-05__pill {
background: oklch(0.28 0.04 285);
}
}
.sn-05__brand {
display: flex;
align-items: center;
gap: 9px;
font-size: 15px;
font-weight: 700;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
white-space: nowrap;
}
.sn-05__logo {
width: 16px;
height: 16px;
border-radius: 50%;
background: conic-gradient(from 210deg,var(--sn-05-acc),oklch(0.85 0.14 200),var(--sn-05-acc));
box-shadow: 0 0 14px -2px var(--sn-05-acc);
}
.sn-05__nav {
display: flex;
align-items: center;
gap: 2px;
margin-inline-start: auto;
}
.sn-05__link {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 13px;
border-radius: 99px;
font-size: 13.6px;
font-weight: 600;
color: var(--sn-05-mut);
text-decoration: none;
transition: color .2s ease,background .2s ease;
}
.sn-05__link:hover {
color: var(--sn-05-ink);
background: oklch(1 0 0/.1);
}
.sn-05__link[aria-current="page"] {
color: var(--sn-05-ink);
background: oklch(1 0 0/.14);
}
.sn-05__cta {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 18px;
border-radius: 99px;
font-size: 13.4px;
font-weight: 670;
color: oklch(0.17 0.03 285);
background: var(--sn-05-ink);
text-decoration: none;
white-space: nowrap;
transition: transform .2s ease,background .2s ease;
}
.sn-05__cta:hover {
transform: translateY(-1px);
background: var(--sn-05-acc);
}
.sn-05__link:focus-visible,
.sn-05__cta:focus-visible,
.sn-05__brand:focus-visible {
outline: 2px solid var(--sn-05-acc);
outline-offset: 2px;
}
.sn-05__hero {
position: relative;
margin-block-start: -70px;
height: min(52svh,420px);
display: grid;
}
.sn-05__img {
grid-area: 1/1;
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(140deg,oklch(0.45 0.18 320),oklch(0.35 0.14 260));
}
.sn-05__herotext {
grid-area: 1/1;
align-self: end;
display: grid;
gap: 8px;
padding: clamp(20px,4vw,40px);
background: linear-gradient(to top,oklch(0.17 0.03 285/.92),transparent);
}
.sn-05__kicker {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--sn-05-acc);
}
.sn-05__title {
font-size: clamp(26px,5vw,44px);
line-height: 1.02;
letter-spacing: -.035em;
font-weight: 720;
text-wrap: balance;
}
.sn-05__sub {
max-width: 46ch;
font-size: 14.5px;
line-height: 1.6;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__main {
display: grid;
}
.sn-05__sec {
scroll-margin-top: 82px;
display: grid;
gap: 10px;
align-content: center;
min-height: 66svh;
padding: clamp(24px,4vw,46px);
border-top: 1px solid oklch(1 0 0/.07);
}
.sn-05__sec:nth-child(even) {
background: oklch(1 0 0/.03);
}
.sn-05__h {
font-size: clamp(19px,2.6vw,26px);
line-height: 1.16;
letter-spacing: -.025em;
font-weight: 690;
text-wrap: balance;
}
.sn-05__p {
max-width: 52ch;
font-size: 14.8px;
line-height: 1.64;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__p code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .85em;
background: oklch(1 0 0/.1);
padding: 2px 6px;
border-radius: 5px;
}
@media (max-width: 560px) {
.sn-05__pill {
padding-inline: 14px 6px;
}
.sn-05__link {
padding: 0 10px;
font-size: 12.8px;
}
.sn-05__cta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.sn-05 * {
transition-duration: .01ms !important;
}
}
/* ── full-page mode: the demo IS the document, so sticky pins against the real viewport ── */
:root:has(.sn-05) {
scroll-behavior: smooth;
scroll-padding-top: 82px;
}
@media (prefers-reduced-motion: reduce) {
:root:has(.sn-05) {
scroll-behavior: auto;
}
}
.sn-05__bar,
.sn-05__barin {
padding-inline: max(clamp(16px,3vw,26px),calc((100% - 1280px)/2));
}
.sn-05__sec {
padding-inline: max(clamp(22px,5vw,44px),calc((100% - 1120px)/2));
}
.sn-05__pagefoot {
display: grid;
place-items: center;
padding: clamp(44px,9vh,110px) 24px;
border-top: 1px solid var(--sn-05-line);
}
.sn-05__pagefootin {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .06em;
color: var(--sn-05-mut);
text-align: center;
}
.sn-05__intro-title,
.sn-05__intro-sub {
text-wrap: balance;
}Here's a working CSS Sticky Navigation 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: Floating Glass Pill Sticky Navbar (Rounded, Backdrop Blur, Elevation)
Source: https://codefronts.com/navigation/css-sticky-navigation/floating-glass-pill-sticky-navbar-rounded-backdrop-blur-elevation/
The detached pill header used across modern product and portfolio sites: lifted away from the viewport edge, rounded to a full radius, and frosted so the page reads through it as it scrolls past. The demo covers the two things that make or break the effect — a genuinely layered rim light instead of a flat border, and a solid fallback where backdrop blur is unavailable.
## HTML
```html
<section class="sn-05" aria-label="Floating glass pill sticky navbar demo">
<header class="sn-05__pill">
<a class="sn-05__brand" href="#sn-05-s1"><span class="sn-05__logo" aria-hidden="true"></span>Lumen</a>
<nav class="sn-05__nav" aria-label="Primary">
<a class="sn-05__link" href="#sn-05-s1" aria-current="page">Work</a>
<a class="sn-05__link" href="#sn-05-s2">Studio</a>
<a class="sn-05__link" href="#sn-05-s3">Journal</a>
</nav>
<a class="sn-05__cta" href="#sn-05-s3">Contact</a>
</header>
<div class="sn-05__hero">
<img class="sn-05__img" src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=1400&auto=format&fit=crop" alt="Abstract flowing colour gradient" width="1400" height="900" loading="lazy" decoding="async">
<div class="sn-05__herotext">
<p class="sn-05__kicker">Glassmorphism</p>
<h2 class="sn-05__title">Chrome that floats</h2>
<p class="sn-05__sub">Scroll — the artwork passes underneath and the pill stays legible the whole way.</p>
</div>
</div>
<main class="sn-05__main">
<section class="sn-05__sec" id="sn-05-s1">
<h3 class="sn-05__h">Blur plus saturation</h3>
<p class="sn-05__p">Blur alone greys out whatever is behind it. <code>saturate(1.8)</code> restores the colour bleeding through, and that is the half of the recipe most tutorials leave out.</p>
</section>
<section class="sn-05__sec" id="sn-05-s2">
<h3 class="sn-05__h">Rim light, not a border</h3>
<p class="sn-05__p">A bright <code>inset 0 1px 0</code> on the top edge and a darker one below make the pill read as a solid piece of glass catching light.</p>
</section>
<section class="sn-05__sec" id="sn-05-s3">
<h3 class="sn-05__h">Legible in every engine</h3>
<p class="sn-05__p">An <code>@supports not (backdrop-filter: blur(1px))</code> block swaps in an opaque surface, so the labels never fall below contrast where blur is unavailable.</p>
</section>
</main>
<footer class="sn-05__pagefoot">
<p class="sn-05__pagefootin">Sticky navigation pattern 05 of 25 · codefronts.com</p>
</footer>
</section>
```
## CSS
```css
.sn-05 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--sn-05-bg);
--sn-05-bg: oklch(0.17 0.03 285);
--sn-05-glass: oklch(0.28 0.04 285);
--sn-05-ink: oklch(0.98 0.005 285);
--sn-05-mut: oklch(0.8 0.02 285);
--sn-05-acc: oklch(0.8 0.15 330);
--sn-05-line: oklch(1 0 0/.16);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--sn-05-ink);
-webkit-font-smoothing: antialiased;
}
.sn-05 *,
.sn-05 *::before,
.sn-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sn-05__pill {
position: sticky;
top: 14px;
z-index: 20;
inline-size: min(100% - 28px,720px);
margin-inline: auto;
display: flex;
align-items: center;
gap: clamp(6px,1.6vw,18px);
min-height: 56px;
padding: 0 8px 0 18px;
border-radius: 999px;
border: 1px solid var(--sn-05-line);
background: color-mix(in oklch,var(--sn-05-glass) 58%,transparent);
backdrop-filter: blur(20px) saturate(1.8);
-webkit-backdrop-filter: blur(20px) saturate(1.8);
box-shadow: 0 18px 40px -18px oklch(0 0 0/.6),inset 0 1px 0 oklch(1 0 0/.22),inset 0 -1px 0 oklch(0 0 0/.28);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.sn-05__pill {
background: oklch(0.28 0.04 285);
}
}
.sn-05__brand {
display: flex;
align-items: center;
gap: 9px;
font-size: 15px;
font-weight: 700;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
white-space: nowrap;
}
.sn-05__logo {
width: 16px;
height: 16px;
border-radius: 50%;
background: conic-gradient(from 210deg,var(--sn-05-acc),oklch(0.85 0.14 200),var(--sn-05-acc));
box-shadow: 0 0 14px -2px var(--sn-05-acc);
}
.sn-05__nav {
display: flex;
align-items: center;
gap: 2px;
margin-inline-start: auto;
}
.sn-05__link {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 13px;
border-radius: 99px;
font-size: 13.6px;
font-weight: 600;
color: var(--sn-05-mut);
text-decoration: none;
transition: color .2s ease,background .2s ease;
}
.sn-05__link:hover {
color: var(--sn-05-ink);
background: oklch(1 0 0/.1);
}
.sn-05__link[aria-current="page"] {
color: var(--sn-05-ink);
background: oklch(1 0 0/.14);
}
.sn-05__cta {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 18px;
border-radius: 99px;
font-size: 13.4px;
font-weight: 670;
color: oklch(0.17 0.03 285);
background: var(--sn-05-ink);
text-decoration: none;
white-space: nowrap;
transition: transform .2s ease,background .2s ease;
}
.sn-05__cta:hover {
transform: translateY(-1px);
background: var(--sn-05-acc);
}
.sn-05__link:focus-visible,
.sn-05__cta:focus-visible,
.sn-05__brand:focus-visible {
outline: 2px solid var(--sn-05-acc);
outline-offset: 2px;
}
.sn-05__hero {
position: relative;
margin-block-start: -70px;
height: min(52svh,420px);
display: grid;
}
.sn-05__img {
grid-area: 1/1;
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(140deg,oklch(0.45 0.18 320),oklch(0.35 0.14 260));
}
.sn-05__herotext {
grid-area: 1/1;
align-self: end;
display: grid;
gap: 8px;
padding: clamp(20px,4vw,40px);
background: linear-gradient(to top,oklch(0.17 0.03 285/.92),transparent);
}
.sn-05__kicker {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--sn-05-acc);
}
.sn-05__title {
font-size: clamp(26px,5vw,44px);
line-height: 1.02;
letter-spacing: -.035em;
font-weight: 720;
text-wrap: balance;
}
.sn-05__sub {
max-width: 46ch;
font-size: 14.5px;
line-height: 1.6;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__main {
display: grid;
}
.sn-05__sec {
scroll-margin-top: 82px;
display: grid;
gap: 10px;
align-content: center;
min-height: 66svh;
padding: clamp(24px,4vw,46px);
border-top: 1px solid oklch(1 0 0/.07);
}
.sn-05__sec:nth-child(even) {
background: oklch(1 0 0/.03);
}
.sn-05__h {
font-size: clamp(19px,2.6vw,26px);
line-height: 1.16;
letter-spacing: -.025em;
font-weight: 690;
text-wrap: balance;
}
.sn-05__p {
max-width: 52ch;
font-size: 14.8px;
line-height: 1.64;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__p code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .85em;
background: oklch(1 0 0/.1);
padding: 2px 6px;
border-radius: 5px;
}
@media (max-width: 560px) {
.sn-05__pill {
padding-inline: 14px 6px;
}
.sn-05__link {
padding: 0 10px;
font-size: 12.8px;
}
.sn-05__cta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.sn-05 * {
transition-duration: .01ms !important;
}
}
/* ── full-page mode: the demo IS the document, so sticky pins against the real viewport ── */
:root:has(.sn-05) {
scroll-behavior: smooth;
scroll-padding-top: 82px;
}
@media (prefers-reduced-motion: reduce) {
:root:has(.sn-05) {
scroll-behavior: auto;
}
}
.sn-05__bar,
.sn-05__barin {
padding-inline: max(clamp(16px,3vw,26px),calc((100% - 1280px)/2));
}
.sn-05__sec {
padding-inline: max(clamp(22px,5vw,44px),calc((100% - 1120px)/2));
}
.sn-05__pagefoot {
display: grid;
place-items: center;
padding: clamp(44px,9vh,110px) 24px;
border-top: 1px solid var(--sn-05-line);
}
.sn-05__pagefootin {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .06em;
color: var(--sn-05-mut);
text-align: center;
}
.sn-05__intro-title,
.sn-05__intro-sub {
text-wrap: balance;
}
```Here's a working CSS Sticky Navigation 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: Floating Glass Pill Sticky Navbar (Rounded, Backdrop Blur, Elevation)
Source: https://codefronts.com/navigation/css-sticky-navigation/floating-glass-pill-sticky-navbar-rounded-backdrop-blur-elevation/
The detached pill header used across modern product and portfolio sites: lifted away from the viewport edge, rounded to a full radius, and frosted so the page reads through it as it scrolls past. The demo covers the two things that make or break the effect — a genuinely layered rim light instead of a flat border, and a solid fallback where backdrop blur is unavailable.
## HTML
```html
<section class="sn-05" aria-label="Floating glass pill sticky navbar demo">
<header class="sn-05__pill">
<a class="sn-05__brand" href="#sn-05-s1"><span class="sn-05__logo" aria-hidden="true"></span>Lumen</a>
<nav class="sn-05__nav" aria-label="Primary">
<a class="sn-05__link" href="#sn-05-s1" aria-current="page">Work</a>
<a class="sn-05__link" href="#sn-05-s2">Studio</a>
<a class="sn-05__link" href="#sn-05-s3">Journal</a>
</nav>
<a class="sn-05__cta" href="#sn-05-s3">Contact</a>
</header>
<div class="sn-05__hero">
<img class="sn-05__img" src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=1400&auto=format&fit=crop" alt="Abstract flowing colour gradient" width="1400" height="900" loading="lazy" decoding="async">
<div class="sn-05__herotext">
<p class="sn-05__kicker">Glassmorphism</p>
<h2 class="sn-05__title">Chrome that floats</h2>
<p class="sn-05__sub">Scroll — the artwork passes underneath and the pill stays legible the whole way.</p>
</div>
</div>
<main class="sn-05__main">
<section class="sn-05__sec" id="sn-05-s1">
<h3 class="sn-05__h">Blur plus saturation</h3>
<p class="sn-05__p">Blur alone greys out whatever is behind it. <code>saturate(1.8)</code> restores the colour bleeding through, and that is the half of the recipe most tutorials leave out.</p>
</section>
<section class="sn-05__sec" id="sn-05-s2">
<h3 class="sn-05__h">Rim light, not a border</h3>
<p class="sn-05__p">A bright <code>inset 0 1px 0</code> on the top edge and a darker one below make the pill read as a solid piece of glass catching light.</p>
</section>
<section class="sn-05__sec" id="sn-05-s3">
<h3 class="sn-05__h">Legible in every engine</h3>
<p class="sn-05__p">An <code>@supports not (backdrop-filter: blur(1px))</code> block swaps in an opaque surface, so the labels never fall below contrast where blur is unavailable.</p>
</section>
</main>
<footer class="sn-05__pagefoot">
<p class="sn-05__pagefootin">Sticky navigation pattern 05 of 25 · codefronts.com</p>
</footer>
</section>
```
## CSS
```css
.sn-05 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--sn-05-bg);
--sn-05-bg: oklch(0.17 0.03 285);
--sn-05-glass: oklch(0.28 0.04 285);
--sn-05-ink: oklch(0.98 0.005 285);
--sn-05-mut: oklch(0.8 0.02 285);
--sn-05-acc: oklch(0.8 0.15 330);
--sn-05-line: oklch(1 0 0/.16);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--sn-05-ink);
-webkit-font-smoothing: antialiased;
}
.sn-05 *,
.sn-05 *::before,
.sn-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sn-05__pill {
position: sticky;
top: 14px;
z-index: 20;
inline-size: min(100% - 28px,720px);
margin-inline: auto;
display: flex;
align-items: center;
gap: clamp(6px,1.6vw,18px);
min-height: 56px;
padding: 0 8px 0 18px;
border-radius: 999px;
border: 1px solid var(--sn-05-line);
background: color-mix(in oklch,var(--sn-05-glass) 58%,transparent);
backdrop-filter: blur(20px) saturate(1.8);
-webkit-backdrop-filter: blur(20px) saturate(1.8);
box-shadow: 0 18px 40px -18px oklch(0 0 0/.6),inset 0 1px 0 oklch(1 0 0/.22),inset 0 -1px 0 oklch(0 0 0/.28);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.sn-05__pill {
background: oklch(0.28 0.04 285);
}
}
.sn-05__brand {
display: flex;
align-items: center;
gap: 9px;
font-size: 15px;
font-weight: 700;
letter-spacing: -.02em;
color: inherit;
text-decoration: none;
white-space: nowrap;
}
.sn-05__logo {
width: 16px;
height: 16px;
border-radius: 50%;
background: conic-gradient(from 210deg,var(--sn-05-acc),oklch(0.85 0.14 200),var(--sn-05-acc));
box-shadow: 0 0 14px -2px var(--sn-05-acc);
}
.sn-05__nav {
display: flex;
align-items: center;
gap: 2px;
margin-inline-start: auto;
}
.sn-05__link {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 13px;
border-radius: 99px;
font-size: 13.6px;
font-weight: 600;
color: var(--sn-05-mut);
text-decoration: none;
transition: color .2s ease,background .2s ease;
}
.sn-05__link:hover {
color: var(--sn-05-ink);
background: oklch(1 0 0/.1);
}
.sn-05__link[aria-current="page"] {
color: var(--sn-05-ink);
background: oklch(1 0 0/.14);
}
.sn-05__cta {
display: flex;
align-items: center;
min-height: 40px;
padding: 0 18px;
border-radius: 99px;
font-size: 13.4px;
font-weight: 670;
color: oklch(0.17 0.03 285);
background: var(--sn-05-ink);
text-decoration: none;
white-space: nowrap;
transition: transform .2s ease,background .2s ease;
}
.sn-05__cta:hover {
transform: translateY(-1px);
background: var(--sn-05-acc);
}
.sn-05__link:focus-visible,
.sn-05__cta:focus-visible,
.sn-05__brand:focus-visible {
outline: 2px solid var(--sn-05-acc);
outline-offset: 2px;
}
.sn-05__hero {
position: relative;
margin-block-start: -70px;
height: min(52svh,420px);
display: grid;
}
.sn-05__img {
grid-area: 1/1;
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(140deg,oklch(0.45 0.18 320),oklch(0.35 0.14 260));
}
.sn-05__herotext {
grid-area: 1/1;
align-self: end;
display: grid;
gap: 8px;
padding: clamp(20px,4vw,40px);
background: linear-gradient(to top,oklch(0.17 0.03 285/.92),transparent);
}
.sn-05__kicker {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--sn-05-acc);
}
.sn-05__title {
font-size: clamp(26px,5vw,44px);
line-height: 1.02;
letter-spacing: -.035em;
font-weight: 720;
text-wrap: balance;
}
.sn-05__sub {
max-width: 46ch;
font-size: 14.5px;
line-height: 1.6;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__main {
display: grid;
}
.sn-05__sec {
scroll-margin-top: 82px;
display: grid;
gap: 10px;
align-content: center;
min-height: 66svh;
padding: clamp(24px,4vw,46px);
border-top: 1px solid oklch(1 0 0/.07);
}
.sn-05__sec:nth-child(even) {
background: oklch(1 0 0/.03);
}
.sn-05__h {
font-size: clamp(19px,2.6vw,26px);
line-height: 1.16;
letter-spacing: -.025em;
font-weight: 690;
text-wrap: balance;
}
.sn-05__p {
max-width: 52ch;
font-size: 14.8px;
line-height: 1.64;
color: var(--sn-05-mut);
text-wrap: pretty;
}
.sn-05__p code {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: .85em;
background: oklch(1 0 0/.1);
padding: 2px 6px;
border-radius: 5px;
}
@media (max-width: 560px) {
.sn-05__pill {
padding-inline: 14px 6px;
}
.sn-05__link {
padding: 0 10px;
font-size: 12.8px;
}
.sn-05__cta {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.sn-05 * {
transition-duration: .01ms !important;
}
}
/* ── full-page mode: the demo IS the document, so sticky pins against the real viewport ── */
:root:has(.sn-05) {
scroll-behavior: smooth;
scroll-padding-top: 82px;
}
@media (prefers-reduced-motion: reduce) {
:root:has(.sn-05) {
scroll-behavior: auto;
}
}
.sn-05__bar,
.sn-05__barin {
padding-inline: max(clamp(16px,3vw,26px),calc((100% - 1280px)/2));
}
.sn-05__sec {
padding-inline: max(clamp(22px,5vw,44px),calc((100% - 1120px)/2));
}
.sn-05__pagefoot {
display: grid;
place-items: center;
padding: clamp(44px,9vh,110px) 24px;
border-top: 1px solid var(--sn-05-line);
}
.sn-05__pagefootin {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 12px;
letter-spacing: .06em;
color: var(--sn-05-mut);
text-align: center;
}
.sn-05__intro-title,
.sn-05__intro-sub {
text-wrap: balance;
}
```How this works
Floating is just a sticky element with a non-zero inset and horizontal auto margins:
.pill{
position: sticky;
top: 14px; /* the gap that makes it float */
inline-size: min(100% - 28px, 720px);
margin-inline: auto;
border-radius: 999px;
background: color-mix(in oklch, var(--surface) 55%, transparent);
backdrop-filter: blur(20px) saturate(1.8);
}Glass is a three-layer illusion and most implementations only ship one. First, blur and saturation boost: blurring alone greys the backdrop, while saturate(1.8) restores the colour bleeding through and is what sells the material. Second, a rim light — a hairline inset 0 1px 0 highlight on the top edge and a darker one at the bottom, so the pill reads as a piece of physical glass catching light rather than a rectangle with a border. Third, real elevation: a wide, soft, low-opacity shadow rather than a tight dark one.
Contrast is the accessibility trade. Translucent chrome over arbitrary page content means the label contrast changes as you scroll, so the background mix here never drops below roughly 55% opacity, and an @supports not (backdrop-filter: blur(1px)) block raises it to fully opaque where blur is unsupported. That keeps text legible in every engine instead of shipping unreadable chrome to a subset of users.
Make it yours
- Light-mode glass: flip the surface token to a near-white and use
brightness(1.05)in the filter chain — dark glass over light pages needs the opposite adjustment. - Squircle instead of pill:
border-radius: 20pxwith the same shadow stack reads as a floating card, which suits wider link sets. - Shrink-on-scroll: combine with demo 06 — animating the pill's
inline-sizeandtoptogether is a very effective scroll transition. - Cheaper blur: drop
saturate()and reduce the radius to 8–10px. Blur radius is the dominant cost on low-end GPUs; halving it roughly halves the paint time.
Gotchas — read before shipping
backdrop-filterneeds a translucent background to blur — with an opaque background there is simply nothing to see through, which is why it 'does nothing' in most bug reports.- Any
filter,transform,opacityorwill-changeon an ancestor creates a containing block that can clip or disable the backdrop entirely. - Blur promotes the element to its own compositor layer and re-samples the backdrop every scroll frame. One pill is free; three stacked translucent bars on a long page are not.
- Safari still needs
-webkit-backdrop-filter. Ship both, always. - A floating pill overlays content: pair it with
scroll-padding-topequal to its height plus its top inset, or anchor targets land underneath it. - Text over glass can fail contrast at certain scroll positions. Keep the surface mix opaque enough for the worst case, not the screenshot.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by :has(), oklch(), color-mix(), backdrop-filter, text-wrap as this demo is written. The core technique itself goes back further — Chrome 111+.
backdrop-filter is supported in Chrome 76, Safari 9 (prefixed) and Firefox 103. color-mix() and oklch() set the quoted floor; the @supports block covers engines without blur.