A navbar sets the tone before someone reads your headline. It also has a practical job: show visitors where they can go and make their next step easy to find. Changing its shape, hierarchy, or emphasis can give a familiar page a different character.
Here are four examples from our own design-style library. Each includes a live desktop and mobile preview and a focused AI prompt you can copy into your coding tool. The example brands are fictional; these are design demonstrations, not client results or conversion studies.
Four navbar designs at a glance
Choose a bold action navbar for an expressive product brand, an editorial masthead for a publication, a minimal navbar for a short journey, or a floating glass navbar for a visual landing page. Start with the number of destinations and the visitor's main task, then choose the visual treatment.
Compare four navbar design approaches Navbar Best for Mobile approach Tradeoff Bold action Expressive product brands Wordmark, action, and Menu Can compete with the hero Editorial masthead Publications and content libraries Compact masthead and section menu Uses more vertical space Quiet minimal Service sites and focused SaaS pages Brand, action, and Menu Needs a short navigation list Floating glass Visual product landing pages Compact glass panel with Menu Contrast depends on the backdrop
01. The bold action navbar
The BuildFast navbar from our Neobrutalism demo uses a thick bottom border, a compact initial mark, and a yellow action with a hard offset shadow. The result is a more forceful hierarchy than the minimal example, even though both use a familiar horizontal layout.
The uppercase wordmark and flat hover fills reinforce the same visual language. This can suit a brand that already uses heavy rules, strong type, and bright accents throughout its interface. The isolated preview omits the source page's announcement strip so you can evaluate the navbar itself.
Your developer tool, template library, or product brand has a deliberately expressive identity.
Giving every nearby element equal weight. If the hero, announcement, navigation, and buttons all compete for attention, the main action becomes harder to identify. Keep secondary navigation plain.
components/ui/bold-navbar.tsx Copy code'use client'
import { useEffect, useId, useRef, useState } from 'react'
type NavLink = { label : string ; href : string }
export type BoldNavbarProps = {
brand ?: string
brandHref ?: string
links ?: NavLink []
currentPath ?: string
logInHref ?: string
actionLabel ?: string
actionHref ?: string
}
const defaultLinks : NavLink [] = [
{ label: 'Product' , href: '/product' },
{ label: 'Templates' , href: '/templates' },
{ label: 'Resources' , href: '/resources' },
{ label: 'Pricing' , href: '/pricing' },
{ label: 'About' , href: '/about' },
]
export function BoldNavbar ({
brand = 'BuildFast' ,
brandHref = '/' ,
links = defaultLinks,
currentPath ,
logInHref = '/log-in' ,
actionLabel = 'Sign up' ,
actionHref = '/sign-up' ,
} : BoldNavbarProps ) {
const [ open , setOpen ] = useState ( false )
const menuId = useId ()
const menuButton = useRef < HTMLButtonElement >( null )
useEffect (() => {
if ( ! open) return
function onEscape ( event : KeyboardEvent ) {
if (event.key === 'Escape' ) {
setOpen ( false )
menuButton.current?. focus ()
}
}
window. addEventListener ( 'keydown' , onEscape)
return () => window. removeEventListener ( 'keydown' , onEscape)
}, [open])
return (
< header className = "relative z-20 border-b-4 border-black bg-white text-black" >
< nav aria-label = "Main navigation" className = "mx-auto flex min-h-[60px] max-w-[1440px] items-center gap-8 px-4 min-[800px]:px-10" >
< a href = {brandHref} className = "inline-flex min-h-11 shrink-0 items-center gap-2.5 text-[17px] font-black tracking-[-.055em] text-black uppercase no-underline" >
< span className = "inline-flex size-8 items-center justify-center border-2 border-black bg-[#ffe600] text-[12px] shadow-[3px_3px_0_#000]" >BF</ span >
{brand}
</ a >
< ul className = "hidden flex-1 items-center gap-1 min-[800px]:flex" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } className = "inline-flex min-h-11 items-center px-3 text-[13px] font-semibold text-black no-underline hover:bg-[#ffe600] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-black aria-[current=page]:bg-[#ffe600]" >
{link.label}
</ a >
</ li >
))}
</ ul >
< div className = "ml-auto flex shrink-0 items-center gap-4" >
< a href = {logInHref} className = "hidden min-h-11 items-center text-[13px] font-semibold text-black no-underline hover:underline min-[800px]:inline-flex" >Log in</ a >
< a href = {actionHref} className = "inline-flex min-h-11 items-center justify-center border-2 border-black bg-[#ffe600] px-4 text-[13px] font-bold text-black no-underline shadow-[4px_4px_0_#000] transition-transform hover:-translate-y-0.5 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-black motion-reduce:transition-none" >
{actionLabel} ↗
</ a >
< button
ref = {menuButton}
type = "button"
aria-label = {open ? 'Close menu' : 'Open menu' }
aria-expanded = {open}
aria-controls = {menuId}
onClick = {() => setOpen (( value ) => ! value)}
className = "inline-flex size-11 cursor-pointer items-center justify-center border-2 border-black bg-white text-xl font-bold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-black min-[800px]:hidden"
>
< span aria-hidden = "true" >{open ? '×' : '☰' }</ span >
</ button >
</ div >
</ nav >
< div id = {menuId} hidden = { ! open} className = "absolute inset-x-0 top-full border-b-4 border-black bg-white px-4 pb-4 min-[800px]:hidden" >
< ul className = "border-t-2 border-black py-2" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } onClick = {() => setOpen ( false )} className = "flex min-h-11 items-center border-b border-black px-2 text-sm font-bold text-black no-underline hover:bg-[#ffe600] aria-[current=page]:bg-[#ffe600]" >
{link.label}
</ a >
</ li >
))}
</ ul >
</ div >
</ header >
)
}
02. The editorial masthead
The Signal header from our Newspaper demo separates utility links, publication identity, and content sections into distinct rows. The large serif title establishes the publication, while the section navigation helps people browse by topic.
This is a useful alternative when your site is a collection rather than a single offer. A reader looking for Technology or Opinion has a different task from someone ready to subscribe. The masthead gives those tasks separate places, with red emphasis on the active section and a dark Subscribe action.
You publish articles, a newsletter archive, or a substantial topic-based library.
The vertical space it occupies. On a small screen, hide nonessential edition metadata and reduce the title size so the content remains within reach. The mobile adaptation here uses a section menu rather than compressing six links into a narrow row.
components/ui/editorial-navbar.tsx Copy code'use client'
import { useEffect, useId, useRef, useState } from 'react'
type NavLink = { label : string ; href : string }
export type EditorialNavbarProps = {
title ?: string
homeHref ?: string
links ?: NavLink []
currentPath ?: string
subscribeHref ?: string
}
const defaultLinks : NavLink [] = [
{ label: 'Front page' , href: '/' },
{ label: 'Technology' , href: '/technology' },
{ label: 'Markets' , href: '/markets' },
{ label: 'Opinion' , href: '/opinion' },
{ label: 'Tools' , href: '/tools' },
{ label: 'Archive' , href: '/archive' },
]
export function EditorialNavbar ({
title = 'The Signal' ,
homeHref = '/' ,
links = defaultLinks,
currentPath ,
subscribeHref = '/subscribe' ,
} : EditorialNavbarProps ) {
const [ open , setOpen ] = useState ( false )
const menuId = useId ()
const menuButton = useRef < HTMLButtonElement >( null )
useEffect (() => {
if ( ! open) return
function onEscape ( event : KeyboardEvent ) {
if (event.key === 'Escape' ) {
setOpen ( false )
menuButton.current?. focus ()
}
}
window. addEventListener ( 'keydown' , onEscape)
return () => window. removeEventListener ( 'keydown' , onEscape)
}, [open])
return (
< header className = "bg-[#f7f4ef] font-[Georgia,serif] text-[#171717]" >
< div className = "bg-[#191919] px-4 text-[#f7f4ef]" >
< div className = "mx-auto flex min-h-8 max-w-[1440px] flex-wrap items-center justify-between gap-x-4 text-[10px] font-semibold tracking-[.12em] uppercase min-[800px]:px-6" >
< span >Independent perspective · Daily edition</ span >
< span className = "hidden min-[500px]:inline" >Stories for curious builders</ span >
</ div >
</ div >
< div className = "mx-auto max-w-[1440px] px-4 pt-5 text-center min-[800px]:px-10 min-[800px]:pt-7" >
< div className = "hidden items-center justify-between border-b border-[#beb8ad] pb-2 text-[10px] font-semibold tracking-[.1em] uppercase min-[800px]:flex" >
< span >Vol. VIII · No. 142</ span >< span >Daily intelligence for builders</ span >< span >Free with subscription</ span >
</ div >
< a href = {homeHref} className = "block py-2 text-[clamp(3rem,8vw,5.5rem)] font-bold leading-none tracking-[-.065em] text-[#171717] no-underline" >
{title}
</ a >
< p className = "pb-5 text-[12px] italic text-[#5e5a53]" >All the analysis that ' s fit to print</ p >
</ div >
< nav aria-label = "Sections" className = "relative mx-auto max-w-[1440px] border-y-2 border-[#171717] px-4 min-[800px]:px-10" >
< div className = "flex min-h-[52px] items-center gap-5 border-b border-[#171717]" >
< ul className = "hidden flex-1 items-center justify-between gap-4 min-[800px]:flex" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } className = "inline-flex min-h-11 items-center border-b-2 border-transparent font-sans text-[11px] font-bold tracking-[.09em] text-[#171717] uppercase no-underline hover:text-[#cc0000] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#cc0000] aria-[current=page]:border-[#cc0000] aria-[current=page]:text-[#cc0000]" >
{link.label}
</ a >
</ li >
))}
</ ul >
< button
ref = {menuButton}
type = "button"
aria-label = {open ? 'Close sections' : 'Open sections' }
aria-expanded = {open}
aria-controls = {menuId}
onClick = {() => setOpen (( value ) => ! value)}
className = "inline-flex min-h-11 cursor-pointer items-center gap-2 font-sans text-xs font-bold tracking-[.08em] uppercase focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#cc0000] min-[800px]:hidden"
>
< span aria-hidden = "true" >{open ? '×' : '☰' }</ span > Sections
</ button >
< a href = {subscribeHref} className = "ml-auto inline-flex min-h-10 shrink-0 items-center bg-[#171717] px-4 font-sans text-[11px] font-bold tracking-[.08em] text-white uppercase no-underline hover:bg-[#cc0000] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#cc0000]" >
Subscribe ↗
</ a >
</ div >
< div id = {menuId} hidden = { ! open} className = "bg-[#f7f4ef] min-[800px]:hidden" >
< ul className = "py-2" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } onClick = {() => setOpen ( false )} className = "flex min-h-11 items-center border-b border-[#d8d1c6] font-sans text-xs font-bold tracking-[.08em] uppercase no-underline hover:text-[#cc0000] aria-[current=page]:text-[#cc0000]" >
{link.label}
</ a >
</ li >
))}
</ ul >
</ div >
</ nav >
</ header >
)
}
03. The quiet, minimal navbar
The Content Bakerz navbar from our Pure Minimalist demo keeps the brand, navigation, and primary action on one restrained horizontal line. A fine bottom rule defines the header without turning it into a large visual block.
The serif wordmark gives the brand a little personality. The navigation links stay muted, while the solid green action is easy to distinguish from Sign in. The design gets its character from spacing and typography rather than extra decoration.
Your site has a small set of destinations and a clear next step, such as exploring a service or starting a product trial.
Adding so many links that the centered group crowds the brand or actions. Shorten labels or reconsider the information structure before shrinking the text.
components/ui/minimal-navbar.tsx Copy code'use client'
import { useEffect, useId, useRef, useState } from 'react'
type NavLink = { label : string ; href : string }
export type MinimalNavbarProps = {
brand ?: string
brandHref ?: string
links ?: NavLink []
currentPath ?: string
signInHref ?: string
actionLabel ?: string
actionHref ?: string
}
const defaultLinks : NavLink [] = [
{ label: 'How it works' , href: '/how-it-works' },
{ label: 'Samples' , href: '/samples' },
{ label: 'Pricing' , href: '/pricing' },
{ label: 'FAQ' , href: '/faq' },
]
export function MinimalNavbar ({
brand = 'Content Bakerz' ,
brandHref = '/' ,
links = defaultLinks,
currentPath ,
signInHref = '/sign-in' ,
actionLabel = 'Get started' ,
actionHref = '/get-started' ,
} : MinimalNavbarProps ) {
const [ open , setOpen ] = useState ( false )
const menuId = useId ()
const menuButton = useRef < HTMLButtonElement >( null )
useEffect (() => {
if ( ! open) return
function onEscape ( event : KeyboardEvent ) {
if (event.key === 'Escape' ) {
setOpen ( false )
menuButton.current?. focus ()
}
}
window. addEventListener ( 'keydown' , onEscape)
return () => window. removeEventListener ( 'keydown' , onEscape)
}, [open])
return (
< header className = "relative z-20 border-b border-[#e2ddd5] bg-[#fafaf7] text-[#1a1917]" >
< nav aria-label = "Main navigation" className = "mx-auto flex h-[60px] max-w-[1440px] items-center gap-3 px-4 min-[800px]:gap-8 min-[800px]:px-10" >
< a href = {brandHref} className = "shrink-0 font-[Georgia,serif] text-[15px] font-medium tracking-[-.04em] text-[#1a1917] no-underline min-[800px]:text-[19px]" >
{brand}
</ a >
< ul className = "hidden flex-1 items-center justify-center gap-7 min-[800px]:flex" >
{links. map (( link ) => (
< li key = {link.href}>
< a
href = {link.href}
aria-current = {currentPath === link.href ? 'page' : undefined }
className = "inline-flex min-h-11 items-center text-sm text-[#77736c] no-underline transition-colors hover:text-[#1f4035] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#1f4035] aria-[current=page]:text-[#1a1917]"
>
{link.label}
</ a >
</ li >
))}
</ ul >
< div className = "ml-auto flex shrink-0 items-center gap-2 min-[800px]:gap-4" >
< a href = {signInHref} className = "hidden min-h-11 items-center text-sm text-[#4a4740] no-underline hover:text-[#1f4035] min-[800px]:inline-flex" >
Sign in
</ a >
< a href = {actionHref} className = "inline-flex min-h-11 items-center justify-center rounded-md bg-[#1f4035] px-3 text-xs font-medium text-white no-underline transition-colors hover:bg-[#2e5e4e] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#1f4035] min-[800px]:px-4 min-[800px]:text-sm" >
{actionLabel}
</ a >
< button
ref = {menuButton}
type = "button"
aria-label = {open ? 'Close menu' : 'Open menu' }
aria-expanded = {open}
aria-controls = {menuId}
onClick = {() => setOpen (( value ) => ! value)}
className = "inline-flex size-11 cursor-pointer items-center justify-center border border-[#e2ddd5] text-[#1a1917] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#1f4035] min-[800px]:hidden"
>
< span aria-hidden = "true" className = "text-xl leading-none" >{open ? '×' : '☰' }</ span >
</ button >
</ div >
</ nav >
< div id = {menuId} hidden = { ! open} className = "absolute inset-x-0 top-full border-b border-[#e2ddd5] bg-[#fafaf7] px-4 pb-4 shadow-[0_12px_20px_rgb(0_0_0/0.06)] min-[800px]:hidden" >
< ul className = "border-t border-[#e2ddd5] py-2" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } onClick = {() => setOpen ( false )} className = "flex min-h-11 items-center border-b border-[#e2ddd5] text-sm text-[#4a4740] no-underline hover:text-[#1f4035] aria-[current=page]:font-semibold" >
{link.label}
</ a >
</ li >
))}
</ ul >
</ div >
</ header >
)
}
04. The floating glass navbar
The Forma navbar from our Glassmorphism demo sits inside a rounded container with space around it. Its translucent surface lets the surrounding color show through, while the violet action gives the visitor a clear point of emphasis.
This treatment works as a distinct object on a landing page. Its maximum width keeps the links together on wide screens, and the generous outer space gives the hero room to frame it. The effect depends on the backdrop: translucency needs something calm behind it to remain readable.
Your product page has a short navigation list and a controlled visual background.
Text crossing busy images or changing colors as the page scrolls. Check contrast against the actual background and provide an opaque fallback for browsers that cannot render the blur.
components/ui/glass-navbar.tsx Copy code'use client'
import { useEffect, useId, useRef, useState } from 'react'
type NavLink = { label : string ; href : string }
export type GlassNavbarProps = {
brand ?: string
brandHref ?: string
links ?: NavLink []
currentPath ?: string
signInHref ?: string
actionLabel ?: string
actionHref ?: string
}
const defaultLinks : NavLink [] = [
{ label: 'Features' , href: '/features' },
{ label: 'How it works' , href: '/how-it-works' },
{ label: 'Pricing' , href: '/pricing' },
]
export function GlassNavbar ({
brand = 'Forma' ,
brandHref = '/' ,
links = defaultLinks,
currentPath ,
signInHref = '/sign-in' ,
actionLabel = 'Get started' ,
actionHref = '/get-started' ,
} : GlassNavbarProps ) {
const [ open , setOpen ] = useState ( false )
const menuId = useId ()
const menuButton = useRef < HTMLButtonElement >( null )
useEffect (() => {
if ( ! open) return
function onEscape ( event : KeyboardEvent ) {
if (event.key === 'Escape' ) {
setOpen ( false )
menuButton.current?. focus ()
}
}
window. addEventListener ( 'keydown' , onEscape)
return () => window. removeEventListener ( 'keydown' , onEscape)
}, [open])
return (
< header className = "px-4 pt-5 text-[#242b28]" >
< nav
aria-label = "Main navigation"
className = "mx-auto max-w-[860px] rounded-[24px] border border-white/80 bg-white/80 p-2 shadow-[0_14px_36px_rgb(47_65_54/0.12),inset_0_1px_0_rgb(255_255_255/0.9)] backdrop-blur-xl min-[800px]:rounded-full"
>
< div className = "flex min-h-12 items-center gap-5 px-3" >
< a href = {brandHref} className = "shrink-0 font-[Georgia,serif] text-[19px] font-semibold tracking-[-.05em] text-[#242b28] no-underline" >
{brand}< span className = "text-[#6b4eff]" >.</ span >
</ a >
< ul className = "hidden flex-1 items-center justify-center gap-6 min-[800px]:flex" >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } className = "inline-flex min-h-11 items-center text-[13px] font-medium text-[#58615b] no-underline hover:text-[#242b28] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#6b4eff] aria-[current=page]:text-[#242b28]" >
{link.label}
</ a >
</ li >
))}
</ ul >
< div className = "ml-auto flex shrink-0 items-center gap-4" >
< a href = {signInHref} className = "hidden min-h-11 items-center text-[13px] font-medium text-[#58615b] no-underline hover:text-[#242b28] min-[800px]:inline-flex" >Sign in</ a >
< a href = {actionHref} className = "inline-flex min-h-11 items-center justify-center rounded-full bg-[#6b4eff] px-4 text-[13px] font-semibold text-white no-underline shadow-[0_5px_14px_rgb(107_78_255/0.2)] hover:bg-[#583ee2] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#6b4eff]" >
{actionLabel}
</ a >
< button
ref = {menuButton}
type = "button"
aria-label = {open ? 'Close menu' : 'Open menu' }
aria-expanded = {open}
aria-controls = {menuId}
onClick = {() => setOpen (( value ) => ! value)}
className = "inline-flex size-11 cursor-pointer items-center justify-center rounded-full text-[#242b28] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#6b4eff] min-[800px]:hidden"
>
< span aria-hidden = "true" className = "text-xl leading-none" >{open ? '×' : '☰' }</ span >
</ button >
</ div >
</ div >
< div id = {menuId} hidden = { ! open} className = "border-t border-[#d8ded5] px-3 pt-2 min-[800px]:hidden" >
< ul >
{links. map (( link ) => (
< li key = {link.href}>
< a href = {link.href} aria-current = {currentPath === link.href ? 'page' : undefined } onClick = {() => setOpen ( false )} className = "flex min-h-11 items-center border-b border-[#d8ded5] text-sm font-medium text-[#3d4841] no-underline hover:text-[#6b4eff] aria-[current=page]:text-[#6b4eff]" >
{link.label}
</ a >
</ li >
))}
</ ul >
</ div >
</ nav >
</ header >
)
}
Which navbar should you choose?
If you are unsure, begin with the minimal version. It gives you a simple baseline for judging whether extra visual treatment helps. Choose the glass version when the surrounding page supports translucency, the editorial version when visitors browse by topic, and the bold version when it matches the rest of your brand.
Before committing, put your real navigation labels into the preview or implementation. Long product names, translated text, and account controls can change how much space you need. A design that works with three short labels may not work with seven destinations.
For mobile, keep the essential action easy to reach and make the menu control explicit. All four interactive examples use a Menu disclosure below 800px. That is an adaptation for this guide; the original full-page demos may use different mobile behavior.
Keep exploring
Explore the complete design styles