Nº 421 of 520
Split navbar with centred wordmark
Links split left and right of a centred serif wordmark over a dark hero. After 80px of scroll it turns into a paper bar and the wordmark shrinks 40px to 24px.
Preview
Use it
Free to use · credit appreciated1 Once, in your project
npx skills add SusanAcharya/Design-Lounge 2 Then ask
Using the Design Lounge skill, build "Split navbar with centred wordmark" (piece navbar-split-centered-logo) in my stack. Match its brief; restyle it onto my product's theme.
No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.
<!-- Design Lounge Nº 421 · "Split navbar with centred wordmark" · www.designlounge.live -->
# Split navbar with centred wordmark
> **Build brief for a coding agent.** Rebuild this piece in the reader's stack. If they haven't said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don't "improve" them.
## What it is
The top bar for Verane, a fictional lake hotel with a dining room. The wordmark sits in the exact centre. Three links sit to its left (Rooms, Dining, Garden). Two links and an outlined "Reserve a table" button sit to its right (Events, Journal). At the top of the page the bar is transparent and its text is ivory over a deep green hero drawn in CSS: a radial gradient, three brass hairline arches, and a brass sun. After 80px of scroll the bar fills with paper, the text turns dark, a 1px hairline appears under it, and the wordmark scales from 40px to 24px. The detail worth copying: a three-column grid of `minmax(0,1fr) auto minmax(0,1fr)` keeps the wordmark in the true centre no matter how long each side is.
## Reference behaviour
1. First frame: scroll is 0. The bar is 104px tall, transparent, with ivory text `#f7f2e8` and a 1px bottom line in `rgba(247,242,232,.18)`.
2. The wordmark "VERANE" is Cormorant Garamond 500, 40px, tracked 0.32em, uppercase. Under it sits "EST. 1931" in Jost 9px, tracked 0.5em, at 80% opacity.
3. "Dining" is the current page. It has `aria-current="page"` and a 1px underline 4px below the text.
4. The hero fills the viewport (100vh, min 640px). Its headline "Supper under the long arches" is 76px serif, centred, 72px from the bottom. "long arches" is italic brass `#d9b878`.
5. The user scrolls. When `scrollY` passes 80, the bar gets the class `solid`. Over 320ms on `cubic-bezier(.2,.7,.2,1)`:
- height goes 104px to 68px,
- background goes transparent to paper `#f4efe4`,
- text goes ivory to ink `#1b1f1c`,
- the bottom line goes to `#d8cfbb`,
- the wordmark scales from 1 to 0.6 (40px to 24px),
- "EST. 1931" fades to 0 over 200ms.
6. The button "Reserve a table" is outlined in `currentColor` over the hero. In the solid bar its border and text turn deep green `#1d3a2f`.
7. Scrolling back above 80px reverses every change on the same timing.
8. Hovering a link draws the 1px underline from left to right over 200ms.
9. Hovering the button fills it. Over the hero: ivory fill, green text. In the solid bar: green fill, paper text.
10. The page scrolls through real sections below the hero: Dining (menu with prices), Rooms (three room cards), Garden, Reserve. Each section is a two-column band with a 1px rule under it.
11. Below 900px wide the links and the button hide. A 44px square menu button appears on the left. The wordmark stays centred.
12. Clicking the menu button opens a paper panel under the bar with all five links and the button at full width. `aria-expanded` flips. Escape closes it and returns focus to the button. Clicking a link closes it.
## Structure
```
1280 x 800 frame, header fixed, padding 0 48px
transparent state, 104px tall
+--------------------------------------------------------------------------+
| ROOMS DINING GARDEN V E R A N E EVENTS JOURNAL [RESERVE A TABLE ->] |
| EST. 1931 |
… 257 more lines. Copy or download for the full brief. Loading the source…Brief
297 linesBuild brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them.
What it is
The top bar for Verane, a fictional lake hotel with a dining room. The wordmark sits in the exact centre. Three links sit to its left (Rooms, Dining, Garden). Two links and an outlined “Reserve a table” button sit to its right (Events, Journal). At the top of the page the bar is transparent and its text is ivory over a deep green hero drawn in CSS: a radial gradient, three brass hairline arches, and a brass sun. After 80px of scroll the bar fills with paper, the text turns dark, a 1px hairline appears under it, and the wordmark scales from 40px to 24px. The detail worth copying: a three-column grid of minmax(0,1fr) auto minmax(0,1fr) keeps the wordmark in the true centre no matter how long each side is.
Reference behaviour
- First frame: scroll is 0. The bar is 104px tall, transparent, with ivory text
#f7f2e8and a 1px bottom line inrgba(247,242,232,.18). - The wordmark “VERANE” is Cormorant Garamond 500, 40px, tracked 0.32em, uppercase. Under it sits “EST. 1931” in Jost 9px, tracked 0.5em, at 80% opacity.
- “Dining” is the current page. It has
aria-current="page"and a 1px underline 4px below the text. - The hero fills the viewport (100vh, min 640px). Its headline “Supper under the long arches” is 76px serif, centred, 72px from the bottom. “long arches” is italic brass
#d9b878. - The user scrolls. When
scrollYpasses 80, the bar gets the classsolid. Over 320ms oncubic-bezier(.2,.7,.2,1):- height goes 104px to 68px,
- background goes transparent to paper
#f4efe4, - text goes ivory to ink
#1b1f1c, - the bottom line goes to
#d8cfbb, - the wordmark scales from 1 to 0.6 (40px to 24px),
- “EST. 1931” fades to 0 over 200ms.
- The button “Reserve a table” is outlined in
currentColorover the hero. In the solid bar its border and text turn deep green#1d3a2f. - Scrolling back above 80px reverses every change on the same timing.
- Hovering a link draws the 1px underline from left to right over 200ms.
- Hovering the button fills it. Over the hero: ivory fill, green text. In the solid bar: green fill, paper text.
- The page scrolls through real sections below the hero: Dining (menu with prices), Rooms (three room cards), Garden, Reserve. Each section is a two-column band with a 1px rule under it.
- Below 900px wide the links and the button hide. A 44px square menu button appears on the left. The wordmark stays centred.
- Clicking the menu button opens a paper panel under the bar with all five links and the button at full width.
aria-expandedflips. Escape closes it and returns focus to the button. Clicking a link closes it.
Structure
1280 x 800 frame, header fixed, padding 0 48px
transparent state, 104px tall
+--------------------------------------------------------------------------+
| ROOMS DINING GARDEN V E R A N E EVENTS JOURNAL [RESERVE A TABLE ->] |
| EST. 1931 |
+------------------------------------------------------------------------- 1px rgba line
| deep green hero, 100vh |
| (arch) ( arch + sun ) (arch) |
| HOTEL AND DINING ROOM · LAKE OSSIACH |
| Supper under the long arches 76px |
| SCROLL KITCHEN 18:30 – 23:00 |
+--------------------------------------------------------------------------+
solid state, 68px tall, paper, 1px #d8cfbb line
| ROOMS DINING GARDEN VERANE (24px) EVENTS JOURNAL [RESERVE A TABLE ->] |
grid: minmax(0,1fr) | auto | minmax(0,1fr), gap 32px
- The bar is a
header,position: fixed, full width,z-index: 10. - Inside, one
divholds the three-column grid, max-width 1280px. - The left links are a
navlabelled “Primary, left” with aul. - The wordmark is a link to the top of the page,
aria-label="Verane, home". - The right column is a flex row,
justify-content: flex-end: anavlabelled “Primary, right” with two links, then the button link. - The menu button is the first child of the grid but is
display: noneabove 900px, so it does not take a column. - The mobile panel is a sibling of the header, fixed under it.
- The hero is a
sectionwith decorativedivs for the arches, sun and floor shade. They carry no text. - The sections below use
sectionwith anh2each. The heroh1is the onlyh1.
Tokens
:root {
/* surfaces */
--paper: #f4efe4; /* solid bar, page */
--paper-2: #ebe4d4; /* card swatches */
--green: #1d3a2f; /* hero, button in solid bar */
--green-2: #142a22; /* hero edge */
/* ink */
--ink: #1b1f1c; /* text in solid bar */
--ink-2: #4a524c; /* body copy */
--on-dark: #f7f2e8; /* text over hero */
--on-dark-2: rgba(247,242,232,.72);
/* accent */
--brass: #b08d4a; /* arches, sun, focus ring */
--brass-2: #8a6a2f; /* kicker text on paper */
--line: #d8cfbb; /* hairline */
/* type */
--serif: "Cormorant Garamond", Georgia, serif;
--sans: "Jost", system-ui, sans-serif;
--fs-mark: 40px;
--fs-link: 12px;
--fs-h1: 76px;
--fs-h2: 52px;
--fs-body: 16px;
/* space */
--space-1: 8px;
--space-2: 16px;
--space-3: 24px;
--space-4: 32px;
--space-6: 48px;
--space-8: 64px;
/* bar */
--bar-h: 104px;
--bar-h-solid: 68px;
--mark-scale-solid: 0.6;
--threshold: 80px;
/* radius and shadow */
--radius: 0;
--shadow: none;
/* motion */
--ease: cubic-bezier(.2,.7,.2,1);
--dur: 320ms;
--dur-micro: 200ms;
}
Typography
| Role | Family | Size | Weight | Line-height | Tracking | Case |
|---|---|---|---|---|---|---|
| Wordmark | Cormorant Garamond | 40px, scaled to 24px | 500 | 1 | 0.32em | upper |
| Wordmark sub | Jost | 9px | 500 | 1 | 0.5em | upper |
| Nav link | Jost | 12px | 500 | 1.6 | 0.22em | upper |
| Button | Jost | 12px | 500 | 1 | 0.2em | upper |
| Hero eyebrow | Jost | 12px | 400 | 1.6 | 0.32em | upper |
| Hero h1 | Cormorant Garamond | 76px | 500 | 1 | -0.01em | sentence |
| Section kicker | Jost | 12px | 400 | 1.6 | 0.28em | upper |
| Section h2 | Cormorant Garamond | 52px | 500 | 1.05 | 0 | sentence |
| Body | Jost | 16px | 400 | 1.6 | 0 | sentence |
| Menu item | Cormorant Garamond | 22px | 500 | 1.6 | 0 | sentence |
The serif is only for the wordmark, headings and menu items. Links and buttons stay in the sans. Add margin-right: -0.32em to the wordmark so its trailing tracking does not push it off centre.
Motion
| Thing | Trigger | Property | From → to | Duration | Easing |
|---|---|---|---|---|---|
| Bar height | scrollY crosses 80 | height | 104px → 68px | 320ms | --ease |
| Bar fill | same | background-color | transparent → #f4efe4 | 320ms | --ease |
| Bar text | same | color | #f7f2e8 → #1b1f1c | 320ms | --ease |
| Bar line | same | border-bottom-color | rgba(247,242,232,.18) → #d8cfbb | 320ms | --ease |
| Wordmark | same | transform | scale(1) → scale(0.6) | 320ms | --ease |
| Sub line | same | opacity | 0.8 → 0 | 200ms | --ease |
| Button | same | border and text colour | currentColor → #1d3a2f | 200ms | --ease |
| Link underline | hover | transform | scaleX(0) → scaleX(1), origin left | 200ms | --ease |
| Button fill | hover | background, colour | none → filled | 200ms | --ease |
- There is no delay and no stagger. Everything moves together.
- Scale the wordmark with
transform, notfont-size, so the row does not reflow during the move. - Reduced motion: set every transition to 0ms. The bar still switches at 80px, it just switches at once. Turn off smooth scroll.
States
- Transparent bar: ivory text, no fill, faint ivory hairline.
- Solid bar: paper fill, ink text,
#d8cfbbhairline, wordmark at 0.6 scale, sub line hidden. - Link resting: no underline.
- Link hover: 1px underline in
currentColor, 4px under the baseline box. - Link current:
aria-current="page"and the same underline, always shown. - Button resting: 1px border, 42px tall, 0 18px padding, no radius.
- Button hover: filled (see Motion).
- Focus-visible: 2px brass outline
#b08d4a, offset 3px, on every link, the wordmark, the button and the menu button. - Menu panel closed:
display: none. Open: paper panel with 1px rules between links. The current link is brass#8a6a2f. - No loading, empty or error state. This is navigation.
Accessibility
- Two
navelements, labelled “Primary, left” and “Primary, right”. Screen readers read them in DOM order, left first. - The wordmark is a link with
aria-label="Verane, home". The sub line is inside it and is decorative. - The current link has
aria-current="page". Only one link carries it. - The menu button has
aria-controls="panel",aria-expanded, and anaria-labelthat switches between “Open menu” and “Close menu”. - Escape closes the panel and returns focus to the menu button.
- Tab order: left links, wordmark, right links, button. On small screens: menu button, wordmark, then the panel links when open.
- Contrast:
#f7f2e8on#1d3a2fis about 11:1.#1b1f1con#f4efe4is about 15:1. Both pass at 12px. - Hit targets: links are 12px text at line-height 1.6 with 10px vertical padding, so about 40px tall. The button is 42px. The menu button is 44px square.
- Decorative hero shapes carry no text and need no labels.
- Icons are inline SVG with
aria-hidden="true".
Responsive rules
- At 1280 and above: the full layout. Bar padding 0 48px. Link gap 32px. Button reads “Reserve a table”.
- At 1180 and below: padding 0 32px, grid gap 24px, link gap 24px, link tracking 0.16em, the button reads “Reserve”.
- At 1024: the same as 1180. Check that the right column does not touch the wordmark.
- Below 900: hide both
navelements and the button. Show the 44px menu button in the left column. The wordmark drops to 28px and the sub line hides. The bar is 72px tall, 60px when solid. The solid wordmark scale is 0.86. - Below 900, also: the hero h1 is 44px, the h2 is 38px, and sections stack to one column with 72px 24px padding. Room cards stack to one column.
- Never let the row wrap. If a product has more than three links per side, collapse earlier instead of shrinking type below 11px.
- The page never scrolls sideways. Use
minmax(0,1fr)on every grid column.
Acceptance checklist
Always
- The wordmark is centred in the viewport within 1px at every width, whatever the link count on each side.
- The bar is transparent with light text at scroll 0 and solid with dark text past the threshold.
- The switch happens at one scroll threshold and reverses when scrolling back.
- The wordmark shrinks with
transform: scale, not by changing font-size. - Exactly one link has
aria-current="page". - The primary action is an outlined button on the right, 42px tall.
- Focus rings are visible on every control in both bar states.
- Below the collapse width a 44px menu button opens a panel;
aria-expandedtracks it; Escape closes it. - Reduced motion removes every transition but keeps both states.
- No horizontal scroll at any width from 360 to 1600.
This demo
- The threshold is 80px of scroll.
- The bar is 104px tall, then 68px when solid.
- The wordmark is “VERANE”, 40px, scaling to 0.6 (24px).
- Left links: Rooms, Dining, Garden. Right links: Events, Journal. Button: “Reserve a table”.
- Dining is the current link.
- Hero is
#1d3a2fwith three brass arches and a brass sun, no images. - The solid bar is
#f4efe4with a#d8cfbbhairline. - The menu collapses below 900px.
Implementation notes
Always: this is one bar with two looks. Do not render two headers and swap them.
The grid that keeps the wordmark centred:
.bar-in {
display: grid;
grid-template-columns: minmax(0,1fr) auto minmax(0,1fr);
align-items: center;
gap: 32px;
height: 100%;
padding: 0 48px;
}
.right-group { display: flex; justify-content: flex-end; align-items: center; gap: 32px; min-width: 0; }
.mark { letter-spacing: .32em; margin-right: -.32em; transform-origin: center; }
The two outer columns are equal, so the middle one sits in the true centre. A flex row with space-between does not do this: with three links on the left and two links plus a button on the right, the wordmark drifts.
The scroll switch, throttled to one frame:
const bar = document.getElementById('bar');
const THRESHOLD = 80;
let ticking = false;
function update() {
bar.classList.toggle('solid', window.scrollY > THRESHOLD);
ticking = false;
}
addEventListener('scroll', () => {
if (!ticking) { requestAnimationFrame(update); ticking = true; }
}, { passive: true });
update();
Call update() once on load so a page restored mid-scroll starts solid.
The state styles:
.bar { height: var(--bar-h); color: var(--on-dark); background: rgba(244,239,228,0);
border-bottom: 1px solid rgba(247,242,232,.18);
transition: height var(--dur) var(--ease), background-color var(--dur) var(--ease),
color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.bar.solid { height: var(--bar-h-solid); background: var(--paper); color: var(--ink); border-bottom-color: var(--line); }
.mark { transition: transform var(--dur) var(--ease); }
.bar.solid .mark { transform: scale(.6); }
.bar.solid .cta { border-color: var(--green); color: var(--green); }
Use rgba(244,239,228,0) as the start colour, not transparent. Some engines fade transparent through grey.
Common mistakes:
- Centring the wordmark with
position: absolute; left: 50%and letting links slide under it at 1024px. - Animating
font-sizeon the wordmark, which reflows the row 20 times during the move. - Forgetting
margin-right: -0.32em, so a tracked wordmark sits a few pixels left of centre. - Putting the hero under the bar with a top margin. The hero starts at 0 and the bar floats over it.
- Leaving ivory text in the solid bar, or dark text over the hero, for one frame on load.
- A drop shadow on the solid bar. The hairline is the separation.
- Using a photo for the hero. This piece draws it in CSS.
- Five links on one side and none on the other. Split them so each side reads as a group.
- A filled button. On a luxe site the reserve action is outlined until hover.
Rebuild order:
- Build the fixed header with the three-column grid.
- Place three links, the wordmark, two links and the button.
- Build the green hero at 100vh with the arches and sun.
- Add the
solidclass styles and the scroll listener. - Add the sections below so the page scrolls.
- Add the 1180 and 900 breakpoints and the menu panel.
- Check focus rings in both states.
- Turn on reduced motion and confirm the switch is instant.
Details
- Palette
- Type
- Cormorant Garamond · Jost
- Motion
- Subtle motion
- Build
- One session
- Tags
Studied
Lama LamaA tiny nav bar can carry the voice. Change its one line for each section.
All sourcesOn the shelves