ScreenshotNeo

BlogHow-to

CSS Headers: How to Style a Website Header

Build a semantic, responsive website header with Flexbox, accessible navigation, visible focus states, and CSS that adapts to your content.

By the ScreenshotNeo team4 October 20268 min read

A website header is the recurring page area for site identity and useful controls such as a logo, search, and primary navigation. Use semantic HTML for that content, then style its layout with CSS. Flexbox works well for a single row; let items wrap or change arrangement at narrower widths when the actual content needs it. There is no universal header height or breakpoint: choose values that keep the content clear and usable.

This guide builds a complete responsive header with a linked wordmark, primary navigation, and a search form. It keeps the DOM order logical, supports keyboard focus, and uses a content-driven breakpoint. You can copy the example into an HTML file and open it in a browser.

1. Start with semantic HTML

Use a page-level <header> for recurring site identity and utilities. Put a <nav> around a significant navigation group, and use ordinary anchors for destinations. Use native controls such as buttons for actions. A header inside an article or section can introduce that content too, but it is not the page-wide banner landmark in the same way as a header in the body context. See the MDN header reference and W3C WAI page regions.

<header class="site-header">
  <div class="header-inner">
    <a class="brand" href="/" aria-label="Acme home">
      <span class="brand-mark" aria-hidden="true">A</span>
      <span>Acme</span>
    </a>

    <nav class="primary-nav" aria-label="Primary">
      <a href="/products">Products</a>
      <a href="/guides">Guides</a>
      <a href="/about">About</a>
    </nav>

    <form class="header-search" action="/search" method="get" role="search">
      <label class="visually-hidden" for="site-search">Search this site</label>
      <input id="site-search" name="q" type="search" placeholder="Search">
      <button type="submit">Search</button>
    </form>
  </div>
</header>

The sample brand mark is decorative, so it is hidden from assistive technology while the link itself has a name. If your logo is an image that conveys the site identity, give the image meaningful alternative text, or provide an accessible name on its link. The search form is optional; remove it if your site does not offer search. Keep headings for content structure rather than choosing heading levels to get a particular visual size.

2. Style the desktop layout with CSS

First create a centered inner container, then align the brand, navigation, and search form. The navigation can consume extra space, while the search stays at its natural width. The focus outline remains visible for keyboard users, and hover styling is not the only indication that a link is interactive.

:root {
  --header-bg: #fff;
  --header-text: #182230;
  --header-muted: #465467;
  --header-border: #d9e0e8;
  --header-accent: #155eef;
  --header-content: 72rem;
}

* { box-sizing: border-box; }

.site-header {
  color: var(--header-text);
  background: var(--header-bg);
  border-bottom: 1px solid var(--header-border);
}

.header-inner {
  width: min(100% - 2rem, var(--header-content));
  min-height: 4.5rem;
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 2rem;
  padding-block: .75rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  flex: 0 0 auto;
  color: inherit;
  font-weight: 700;
  font-size: 1.15rem;
  text-decoration: none;
}

.brand-mark {
  display: grid;
  width: 2rem;
  aspect-ratio: 1;
  place-items: center;
  border-radius: .5rem;
  color: #fff;
  background: var(--header-accent);
}

.primary-nav {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  gap: clamp(.75rem, 2vw, 1.75rem);
}

.primary-nav a {
  color: var(--header-muted);
  font-weight: 600;
  text-decoration: none;
}

.primary-nav a:hover { color: var(--header-accent); }

.header-search {
  display: flex;
  flex: 0 1 17rem;
  gap: .4rem;
}

.header-search input {
  width: 100%;
  min-width: 0;
  padding: .55rem .7rem;
  border: 1px solid var(--header-border);
  border-radius: .4rem;
  font: inherit;
}

.header-search button {
  padding: .55rem .75rem;
  border: 0;
  border-radius: .4rem;
  color: #fff;
  background: var(--header-accent);
  font: inherit;
  font-weight: 600;
}

.site-header a:focus-visible,
.site-header button:focus-visible,
.site-header input:focus-visible {
  outline: 3px solid #f5a524;
  outline-offset: 3px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

3. Make the header fit narrower screens

Test the header with the real logo, translated labels, and longest expected navigation names. When the row no longer fits, a simple option is to wrap the navigation and search onto another line. This example uses a 46rem breakpoint as a design choice, not a standard. Adjust it based on where your content starts to feel crowded.

@media (max-width: 46rem) {
  .header-inner {
    flex-wrap: wrap;
    gap: .75rem 1rem;
    padding-block: .85rem;
  }

  .brand { margin-right: auto; }

  .primary-nav {
    order: 3;
    flex: 1 0 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: .5rem 1rem;
  }

  .header-search { flex: 0 1 14rem; }
}

@media (max-width: 25rem) {
  .header-search {
    flex: 1 0 100%;
  }

  .header-search button { flex: 0 0 auto; }
}

This arrangement leaves all navigation links visible. If you choose a collapsed mobile menu instead, implement it as a real button with an accessible name, expose its expanded state with aria-expanded, and ensure the menu remains reachable by keyboard. CSS alone can change appearance, but it does not create the interaction behavior of an operable menu button.

4. Choose a layout that fits your content

Pattern Works well when Check
Single row The brand, navigation, and utilities fit together at the target width. No clipping, overlap, or cramped controls as the viewport shrinks.
Wrapping row You want navigation to remain visible without adding menu behavior. Wrapped items retain clear grouping and sensible reading order.
Collapsed navigation The full navigation cannot fit and a compact menu is appropriate. The button works with keyboard and assistive technology, and links are discoverable.

Use the pattern that matches your content. Preserve a logical source order in the HTML so reading and keyboard order make sense even when CSS changes the visual arrangement. MDN’s HTML accessibility guidance explains why logical order matters. W3C’s H69 heading technique describes headings at the start of content sections; it is a technique, not a rule to add headings solely for styling.

5. Optional header details

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
}

Sticky positioning can keep navigation available while scrolling, but it occupies screen space and can cover content if the page uses anchor links. Check that focused elements and linked sections are not hidden behind it. A header can also be fixed, but fixed positioning removes it from normal document flow, so reserve space for it deliberately.

Current page indication

<a href="/guides" aria-current="page">Guides</a>

Use aria-current="page" on the link for the current page, and style it visibly:

.primary-nav a[aria-current="page"] {
  color: var(--header-text);
  text-decoration: underline;
  text-decoration-thickness: .15em;
  text-underline-offset: .3em;
}

Color and contrast

Choose text and control colors that remain legible against the header background. Keep focus indicators distinct from both the background and nearby content. Avoid removing outlines unless you replace them with an equally visible focus treatment.

6. Test the finished header

  1. Resize the viewport gradually and look for clipping, overlap, awkward gaps, and unexpected wrapping.
  2. Use the keyboard to move through the logo, links, search field, and button; confirm the visible focus indicator stays easy to see.
  3. Check that the order when tabbing matches the sensible reading order.
  4. Try long labels, browser zoom, and narrow widths. Ensure controls remain available and text does not disappear.
  5. Confirm the logo link, navigation destinations, and search form behavior match the site.
  6. If the header is sticky, test anchor links and keyboard focus near the top of the page.

7. Troubleshooting

Symptom Likely cause Fix
Navigation overlaps the logo or search The combined content is wider than the available row. Reduce decorative spacing carefully, allow wrapping, or move to a compact navigation layout at a content-tested breakpoint.
Search field collapses to almost nothing Flex items compete for space and the input has no useful minimum width. Give the form a suitable flex basis, set the input to min-width: 0, and let it move to a new row on smaller screens.
Focus is hard to see Default outlines were removed or blend into the header. Apply a high-visibility :focus-visible outline to links and controls.
Menu links cannot be reached on mobile A visual menu toggle was added without functional state or correct control behavior. Use a native button, connect it to the menu state, expose aria-expanded, and verify keyboard operation.
Sticky header hides a section heading In-page navigation scrolls the target under the sticky area. Account for the header in the page’s anchor scrolling behavior and test target visibility.
Screen reader announces an unexpected banner A nested content header is being mistaken for the site-wide header. Use header elements for their semantic context and inspect landmark behavior; nested headers are introductions to their containing content.

8. Performance, reliability, and cost

A header built from semantic HTML and CSS does not require a JavaScript framework. Keeping the navigation visible avoids the extra script and state handling that a menu toggle needs. If you add a collapsed menu, test its behavior after changes to navigation labels and at zoomed text sizes so it remains operable. There is no universal best breakpoint or header dimension: content, available width, and the selected behavior determine those values.

To inspect how a header renders at a target URL, a screenshot can reveal clipping or wrapping that is easy to miss in code review. For repeatable checks across URLs, use the same viewport and browser conditions each time; screenshot output is a visual aid, not a substitute for keyboard and assistive technology checks.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. Use the API to capture a page after updating its header CSS, or connect its MCP server so Claude, Cursor, or another MCP client can take screenshots.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Replace the example URL with your page. The ScreenshotNeo API documentation covers request options. Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed, and response headers identify the page verdict and billing status. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

What belongs in a website header?

Common items include the site identity, primary navigation, and useful utilities such as search. Include only what visitors need to identify the site or reach key destinations.

Does every header need a navigation element?

No. Use <nav> for a significant group of navigation links. A header can contain other useful content without a navigation group.

Is 500px the right breakpoint?

It is one example used by a responsive header tutorial, not a universal standard. Set the breakpoint where your own content stops fitting comfortably.

Should the header be sticky?

Only if keeping it visible helps the page’s use. Test how much screen space it occupies and whether it obscures focused content or in-page link targets.

Sources