Nav bar
Two floating glass pills — logo left, links right. The nav hovers over the page without a solid background, using backdrop-filter blur to stay legible over any content. The wordmark swaps color when scrolling over dark sections. This is the production landing nav, faithfully reproduced.
Variants
Default is the resting state — both pills use --glass-bg (72% opacity cream) with --glass-border. The backdrop blur makes it readable over any background without a heavy opaque bar.
Over dark — when the page scrolls into a dark section, add .over-dark to the <nav>. The wordmark color flips from --wm-teal to --dark-canvas (near-black) so it reads on the now-dark glass. The links pill gets a dark glass treatment.
Scrolled — after 8px of scroll, add .scrolled to the <nav>. The glass opacity increases to 92%, and a visible 1px border appears. This prevents the pills from feeling unmoored when scrolled away from the hero.
Structure
| Element | Height | Padding | Notes |
|---|---|---|---|
| Nav shell | — | 16px top | Fixed, pointer-events none — children restore pointer-events |
| Logo pill | 44px | 6px all-round | Wordmark is 18px Bricolage Grotesque |
| Links pill | 44px | 6px all-round, 2px gap between links | Last link is always the CTA |
| Nav link (text) | — | 7px 14px | 14px/500 Onest, pill border-radius |
| CTA link | — | 7px 14px | Ink fill, paper text, 600 weight |
States
| State | Visual change | Trigger |
|---|---|---|
| Default (at top) | Glass at 72% opacity, no border | Page Y = 0 |
| Scrolled | Glass at 92% opacity, 1px --ink-line border | window.scrollY > 8 → add .scrolled |
| Over dark | Wordmark flips to dark color, links pill gets dark glass | IntersectionObserver on dark sections → add .over-dark |
| Link hover | rgba(23,21,19,0.04) bg, full ink text | pointer hover |
| Link pressed | scale(0.97) | :active |
| CTA hover | --teal-deep background | pointer hover |
| Mobile (<720px) | Text links hidden — only logo + CTA visible | CSS media query |
On dark surfaces
The dark behavior is driven by IntersectionObserver — when a dark-background section enters the viewport, .over-dark is toggled on the <nav> element. This triggers the wordmark color transition (200ms ease-out) and the links pill dark glass. Remove .over-dark when the dark section exits.
Anatomy
| Part | Element | Notes |
|---|---|---|
| Nav shell | <nav class="nav"> | Fixed, full-width, pointer-events none. Only pills are interactive. |
| Row | .nav-row | Flexbox, space-between, 16px top padding, 32px side padding. |
| Logo pill | .nav-logo-pill wrapping .nav-wordmark | Glass pill. Wraps wordmark only — no icon, no avatar. |
| Links pill | .nav-links-pill | Glass pill wrapping 1–4 links. Last link is always .cta. |
| Nav link | .nav-link | Transparent by default. Hover: warm fill. Active: scale(0.97). |
| CTA | .nav-link.cta | Ink fill inside the links pill — the one action that stands out. |
Usage
IntersectionObserver to toggle .over-dark — don't try to detect this from scroll position. The observer fires when the dark section's boundary crosses the nav, regardless of scroll speed.
Accessibility
<nav>, which is a landmark element. Add aria-label="Main navigation" to distinguish it from other <nav> elements on the page (e.g., the sidebar).
<a href="#main-content" class="skip-link">Skip to content</a>. Style it visually hidden until focused.
.over-dark is purely visual — it has no semantic change. No ARIA updates needed.
Code
HTML
<nav class="nav" aria-label="Main navigation"> <div class="nav-row"> <a href="/" class="nav-logo-pill" aria-label="Settld home"> <span class="nav-wordmark" aria-hidden="true">settld</span> </a> <div class="nav-links-pill"> <a href="#features" class="nav-link">Features</a> <a href="#pricing" class="nav-link">Pricing</a> <a href="#waitlist" class="nav-link cta">Join waitlist →</a> </div> </div> </nav>
JavaScript — scroll + dark-section detection
const nav = document.querySelector('.nav'); // Scroll: strengthen glass after 8px window.addEventListener('scroll', () => { nav.classList.toggle('scrolled', window.scrollY > 8); }, { passive: true }); // Dark sections: swap wordmark color const darkSections = document.querySelectorAll('[data-dark-section]'); const observer = new IntersectionObserver(entries => { const anyDark = entries.some(e => e.isIntersecting); nav.classList.toggle('over-dark', anyDark); }, { rootMargin: '-64px 0px 0px 0px', threshold: 0 }); darkSections.forEach(s => observer.observe(s));
CSS classes
| Class | Purpose |
|---|---|
.nav | Fixed shell, pointer-events none, z-index 50 |
.nav.scrolled | Opaque glass (92%), visible border — added via JS on scroll |
.nav.over-dark | Wordmark color swap — added via IntersectionObserver |
.nav-row | Flex row, space-between, restores pointer-events |
.nav-logo-pill | Left glass pill — wraps wordmark |
.nav-wordmark | Bricolage Grotesque 18px teal wordmark |
.nav-links-pill | Right glass pill — wraps links |
.nav-link | Text link with hover fill and press scale |
.nav-link.cta | Ink-fill primary action inside the links pill |
Design tokens used
| Token | Value | Role |
|---|---|---|
--glass-bg | rgba(251,248,240,0.72) | Default pill background |
--glass-border | rgba(255,255,255,0.55) | Default pill border |
--wm-teal | #2A9D8F | Wordmark teal on light |
--shadow-md | see tokens.css | Pill shadow |
--r-pill | 999px | Pill border-radius |
--z-nav | 50 | Fixed z-index |
--ink | #171513 | CTA fill |
--teal-deep | #0A5F4F | CTA hover fill |
--d-fast | 140ms | Link transitions |