Skip to main contentSkip to docs navigation

Build responsive site and application navigation with branding, nav links, forms, and a drawer-based mobile menu — composable from Chassis sub-components.

@layer components
Requires JavaScript
Container queries
Depends onDrawer, Nav
Context tokens

Overview

The navbar is the primary navigation surface for a site or application. It composes a branding area, a set of navigation links, optional forms or text, and a drawer-based mobile menu — all wrapped in a single <nav> element that is responsive by default.

Key features

  • Collapses into a slide-in drawer at a chosen breakpoint via the .{breakpoint}:navbar-expand modifier
  • Built-in sub-components for branding (.navbar-brand), navigation (.navbar-nav), forms, and inline text (.navbar-text)
  • Container-query based — the expand transition responds to the navbar's own width, not the viewport
  • Themed through standard Chassis context classes (.context.<color>) and data-cx-theme="dark"
  • Translucent variant for navbars positioned over content
  • Integrates with the Drawer, Collapse, and Menu JavaScript plugins

Basic structure

A complete navbar combines five elements: the .navbar wrapper, an inner container (typically .container.fluid), a .navbar-brand, a .navbar-toggler button, and a <dialog class="drawer"> that holds the navigation when collapsed. Below the chosen .{breakpoint}:navbar-expand breakpoint, the toggler reveals the drawer; above it, the drawer's contents flow inline and the toggler hides automatically.

Resize the example below to preview the transition between drawer and inline modes.

HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarDrawer" aria-controls="navbarDrawer" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarDrawer" aria-labelledby="navbarDrawerLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarDrawerLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body mb-small medium:mb-0">
        <ul class="navbar-nav me-auto">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item">
            <button class="nav-link menu-toggle" type="button" data-cx-toggle="menu" aria-expanded="false">
              Menu
            </button>
            <div class="menu">
              <a class="menu-item" href="#">Action</a>
              <a class="menu-item" href="#">Another action</a>
              <hr class="menu-divider">
              <a class="menu-item" href="#">Something else here</a>
            </div>
          </li>
          <li class="nav-item">
            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
          </li>
        </ul>
        <form class="hstack gap-small" role="search">
          <input class="form-input" type="search" placeholder="Search" aria-label="Search"/>
          <button class="button neutral smooth icon-only" type="submit" aria-label="Search">
            <svg class="icon" aria-hidden="true"><use href="#search-solid"></use></svg>
          </button>
        </form>
      </div>
    </dialog>
  </div>
</nav>

Content components

The navbar exposes a small set of sub-components — brand, nav, forms, and inline text — that combine into a complete navigation surface. Each can appear independently or together inside the same .navbar.

Branding

The .navbar-brand sets the project or product identity at the start of the navbar. It works on any element, but an anchor is the most common choice since the brand typically links to the home page.

Text

Wrap a text label in any element carrying .navbar-brand.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
  </div>
</nav>

Image

Replace the text with an <img> for an image-only brand.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container">
    <a class="navbar-brand" href="#">
      <img src="/static/images/site-logo.svg" alt="Chassis CSS" height="24">
    </a>
  </div>
</nav>

Image and text

Combine an image and text in the same brand element. The .d-inline-block and .align-text-top utilities keep the image aligned with the surrounding text baseline.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">
      <img src="/static/images/site-logo.svg" alt="Logo" height="24" class="d-inline-block align-text-top">
      <span class="ms-xsmall font-strong">CSS</span>
    </a>
  </div>
</nav>

Navbar navigation uses .nav-link inside a .navbar-nav container. The container holds the links inside the drawer below the expand breakpoint and lays them out inline above it, where they grow to occupy the available horizontal space.

Mark the current link with .active and aria-current="page".

HTML
<nav class="navbar small:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarNav" aria-labelledby="navbarNavLabel">
      <div class="drawer-header">
        <h3 class="drawer-title" id="navbarNavLabel">Menu</h3>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">About</a>
          </li>
          <li class="nav-item">
            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
          </li>
        </ul>
      </div>
    </dialog>
  </div>
</nav>

Alternative markup

The <ul> / <li> structure is optional. A plain <div class="navbar-nav"> containing direct <a class="nav-link"> children produces the same result, and pairs naturally with .nav-pills or other nav variants.

HTML
<nav class="navbar small:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarNavAltMarkup" aria-labelledby="navbarNavAltMarkupLabel">
      <div class="drawer-header">
        <h3 class="drawer-title" id="navbarNavAltMarkupLabel">Menu</h3>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <div class="nav-pills navbar-nav">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
          <a class="nav-link" href="#">Link</a>
          <a class="nav-link" href="#">About</a>
          <a class="nav-link disabled" aria-disabled="true">Disabled</a>
        </div>
      </div>
    </dialog>
  </div>
</nav>

With menus

The Menu plugin nests inside a .nav-item, with the trigger marked by data-cx-toggle="menu". The wrapping .nav-item is required so the menu positions correctly relative to its trigger.

HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarNavMenu" aria-controls="navbarNavMenu" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarNavMenu" aria-labelledby="navbarNavMenuLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarNavMenuLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <ul class="navbar-nav">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">About</a>
          </li>
          <li class="nav-item">
            <button class="nav-link" type="button" data-cx-toggle="menu" aria-expanded="false">
              Menu
            </button>
            <div class="menu">
              <a class="menu-item" href="#">Action</a>
              <a class="menu-item" href="#">Another action</a>
              <a class="menu-item" href="#">Something else here</a>
            </div>
          </li>
        </ul>
      </div>
    </dialog>
  </div>
</nav>

Forms

Form controls placed inside a navbar use the standard form classes. The navbar's flex layout defaults to justify-content: space-between, so a brand on the left and a form on the right align automatically without additional utilities.

A standalone search form:

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <form class="d-flex" role="search">
      <input class="form-input me-small" type="search" placeholder="Search" aria-label="Search"/>
      <button class="button primary outline" type="submit">Search</button>
    </form>
  </div>
</nav>

The same form alongside a brand — the flex layout pushes the form to the opposite edge:

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand">Navbar</a>
    <form class="d-flex" role="search">
      <input class="form-input me-small" type="search" placeholder="Search" aria-label="Search"/>
      <button class="button primary outline" type="submit">Search</button>
    </form>
  </div>
</nav>

Input groups work too. When the navbar is essentially a form, using the <form> element as the inner container saves a level of markup.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <form class="container fluid">
    <div class="input-group">
      <span class="input-addon" id="basic-addon1">@</span>
      <input type="text" class="form-input" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1"/>
      <button type="submit" class="button primary">Submit</button>
    </div>
  </form>
</nav>

Mixed button sizes inside a navbar form align via the same flex layout, with vertical alignment utilities available for finer adjustment.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <form class="container fluid justify-content-start">
    <button class="button primary outline me-small" type="button">Main button</button>
    <button class="button small secondary outline" type="button">Smaller button</button>
    <button type="submit" hidden>Submit</button>
  </form>
</nav>

Text content

The .navbar-text class adjusts vertical alignment and horizontal spacing for inline strings of text inside the navbar.

HTML
<nav class="navbar bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <span class="navbar-text">
      Navbar text with an inline element
    </span>
  </div>
</nav>

Text combines naturally with other navbar components inside the drawer body.

HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar w/ text</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarText" aria-labelledby="navbarTextLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarTextLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <ul class="navbar-nav me-auto mb-small medium:mb-0">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">About</a>
          </li>
        </ul>
        <span class="navbar-text">
          Navbar text with an inline element
        </span>
      </div>
    </dialog>
  </div>
</nav>

Theming

The navbar inherits Chassis's full theming system — dark mode toggles, context color variants, and a translucent variant for over-content navbars.

Dark mode

Apply data-cx-theme="dark" directly to the .navbar element to opt a single navbar into the dark theme regardless of the page's color scheme.

HTML
<nav class="navbar medium:navbar-expand bg-even" data-cx-theme="dark" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Dark navbar</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarDarkDrawer" aria-controls="navbarDarkDrawer" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarDarkDrawer" aria-labelledby="navbarDarkDrawerLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarDarkDrawerLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body mb-small medium:mb-0">
        <ul class="navbar-nav me-auto">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item">
            <button class="nav-link" type="button" data-cx-toggle="menu" aria-expanded="false">
              Menu
            </button>
            <div class="menu">
              <a class="menu-item" href="#">Action</a>
              <a class="menu-item" href="#">Another action</a>
              <hr class="menu-divider">
              <a class="menu-item" href="#">Something else here</a>
            </div>
          </li>
          <li class="nav-item">
            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
          </li>
        </ul>
        <form class="hstack gap-small" role="search">
          <input class="form-input" type="search" placeholder="Search" aria-label="Search"/>
          <button class="button primary outline icon-only" type="submit" aria-label="Search">
            <svg class="icon" aria-hidden="true"><use href="#search-solid"></use></svg>
          </button>
        </form>
      </div>
    </dialog>
  </div>
</nav>

Context variants

The .context.<color> modifier swaps the navbar's color palette to a semantic context. Combine with .solid for a saturated fill, with bg-* utilities for custom backgrounds, or with data-cx-theme to mix theme and context independently.

HTML
<nav class="navbar context primary solid" aria-label="Main navigation">
  <!-- Solid primary on default theme -->
</nav>

<nav class="navbar context primary bg-even" data-cx-theme="dark" aria-label="Main navigation">
  <!-- Primary tint on a dark sub-tree -->
</nav>

<nav class="navbar context primary bg-even" data-cx-theme="light" aria-label="Main navigation">
  <!-- Primary tint on a light sub-tree -->
</nav>

Translucent

The .translucent modifier blurs and saturates whatever sits behind the navbar — useful when the navbar is positioned over a hero image, video, or scrollable content.

HTML
<nav class="navbar translucent medium:navbar-expand" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Navbar</a>
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link active" aria-current="page" href="#">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">About</a>
      </li>
    </ul>
  </div>
</nav>

Layout options

The navbar can be wrapped in a container, hold its own container, sit fixed at the top or bottom of the viewport, or stick during scroll.

Containers

A navbar wrapped in a .container is centered on the page; the inner container is still required for the navbar's own padding. Placing the inner container directly inside .navbar instead centers only the navbar's contents while keeping its background full-width.

HTML
<div class="container">
  <nav class="navbar large:navbar-expand bg-even" aria-label="Main navigation">
    <div class="container fluid">
      <a class="navbar-brand" href="#">Navbar</a>
    </div>
  </nav>
</div>

Any responsive container variant is available to control how wide the navbar's contents appear.

HTML
<nav class="navbar large:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container medium">
    <a class="navbar-brand" href="#">Navbar</a>
  </div>
</nav>

Placement

The position utilities.fixed-top, .fixed-bottom, .sticky-top, .sticky-bottom — pull the navbar out of normal flow or pin it during scroll. Fixed navbars use position: fixed and may require a compensating offset on the body (e.g. padding-top) to prevent content overlap.

HTML
<nav class="navbar bg-evident">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Default</a>
  </div>
</nav>

Advanced features

Beyond the basic structure, the navbar exposes controls for tuning its responsive transition, the drawer's slide direction, the toggler's position, and integration with content that lives outside the .navbar element itself.

Responsive behavior

The .{breakpoint}:navbar-expand modifier controls when the navbar transitions between drawer mode and inline mode:

  • .small:navbar-expand — drawer below the small breakpoint, inline at small and above
  • .medium:navbar-expand — drawer below medium, inline at medium and above
  • .large:navbar-expand — drawer below large, inline at large and above
  • .xlarge:navbar-expand — drawer below xlarge, inline at xlarge and above
  • .2xlarge:navbar-expand — drawer below 2xlarge, inline at 2xlarge and above
  • .navbar-expand — inline at all widths (toggler hidden, drawer markup renders flat inside the navbar)
  • No .navbar-expand class — drawer at all widths (toggler always visible, the drawer must be opened to access the nav)

The breakpoint trigger is implemented with container queries, so the transition responds to the navbar's own width rather than the viewport width.

Drawer placement

The drawer slides in from any side via the .drawer-{position} classes:

  • .drawer-start — left edge (or right in RTL)
  • .drawer-end — right edge (or left in RTL); used as the default in this doc's examples
  • .drawer-top — top edge
  • .drawer-bottom — bottom edge

The examples below omit the .{breakpoint}:navbar-expand class so the drawer is always visible regardless of viewport width.

HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Left Drawer</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarLeftDrawer" aria-controls="navbarLeftDrawer" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-start" tabindex="-1" id="navbarLeftDrawer" aria-labelledby="navbarLeftDrawerLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarLeftDrawerLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <ul class="navbar-nav me-auto mb-small medium:mb-0">
          <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
          <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
        </ul>
      </div>
    </dialog>
  </div>
</nav>
HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <a class="navbar-brand" href="#">Top Drawer</a>
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarTopDrawer" aria-controls="navbarTopDrawer" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-top" tabindex="-1" id="navbarTopDrawer" aria-labelledby="navbarTopDrawerLabel">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarTopDrawerLabel">Menu</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <ul class="navbar-nav me-auto mb-small medium:mb-0">
          <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
          <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
        </ul>
      </div>
    </dialog>
  </div>
</nav>

Toggle button

The .navbar-toggler has no fixed position — its location within the navbar is determined by its order in the markup relative to other flex siblings. Placing it before .navbar-brand renders it on the left; placing it after renders it on the right. The flex container distributes spacing between siblings automatically, so no positioning utility classes are required.

With no .navbar-brand visible (the brand lives inside the drawer):

HTML
<nav class="navbar medium:navbar-expand bg-even" aria-label="Main navigation">
  <div class="container fluid">
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
    <dialog class="drawer drawer-end" tabindex="-1" id="navbarTogglerDemo01" aria-labelledby="navbarTogglerDemo01Label">
      <div class="drawer-header">
        <h2 class="drawer-title" id="navbarTogglerDemo01Label">Hidden brand</h2>

        <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
      </div>
      <div class="drawer-body">
        <a class="navbar-brand" href="#">Hidden brand</a>
        <ul class="navbar-nav me-auto mb-small medium:mb-0">
          <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
          <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
          <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
        </ul>
        <form class="d-flex" role="search">
          <input class="form-control me-small" type="search" placeholder="Search" aria-label="Search"/>
          <button class="button outline success" type="submit">Search</button>
        </form>
      </div>
    </dialog>
  </div>
</nav>

External content

The drawer trigger matches on id and data-cx-target, so the controlled drawer can live anywhere in the document — not necessarily inside the .navbar. Use this when the controlled content is structurally separate from the navigation surface.

Toggleable via the navbar toggler.
HTML
<dialog class="drawer drawer-top" tabindex="-1" id="navbarToggleExternalContent" data-cx-theme="dark" aria-labelledby="navbarToggleExternalContentLabel">
  <div class="drawer-header">
    <h2 class="drawer-title" id="navbarToggleExternalContentLabel">Collapsed content</h2>

    <button type="button" class="close-button" data-cx-dismiss="drawer" aria-label="Close"></button>
  </div>
  <div class="drawer-body">
    <span class="fg-main">Toggleable via the navbar toggler.</span>
  </div>
</dialog>
<nav class="navbar bg-body" data-cx-theme="dark" aria-label="Main navigation">
  <div class="container fluid">
    <button class="button icon-only navbar-toggler" type="button" data-cx-toggle="drawer" data-cx-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
      <svg class="icon navbar-toggler-icon" aria-hidden="true"><use href="#bars-outline"></use></svg>
    </button>
  </div>
</nav>

When the controlled container precedes the toggler in document order, keyboard and assistive technology users may have trouble locating the newly revealed content. Move focus to the drawer programmatically on open, and keep the aria-controls attribute pointing at the controlled element so the toggler-to-content relationship is exposed.

Accessibility

An accessible navbar relies on semantic markup and ARIA attributes that assistive technologies can interpret.

  • Use a <nav> element (or role="navigation" on a generic element) so the navbar is exposed as a landmark region.
  • Mark the current page with aria-current="page" on the active .nav-link, or aria-current="true" for the current item in a non-page set.
  • The .navbar-toggler must carry aria-label, aria-controls (pointing at the drawer's id), and aria-expanded (kept in sync by the Drawer plugin).

Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.

CSS

This component can be customized through Sass variables at compile time.

Custom properties

This component exposes CSS custom properties to control its appearance at runtime.

--padding-x: var(--navbar-padding-x, #{$navbar-padding-x});
--padding-y: var(--navbar-padding-y, #{$navbar-padding-y});
--fg-color: var(--navbar-fg-color, #{$navbar-fg-color});
--bg-color: var(--navbar-bg-color, #{$navbar-bg-color});
--nav-gap: var(--navbar-nav-gap, #{$navbar-nav-gap});
--link-padding-x: var(--navbar-link-padding-x, #{$navbar-link-padding-x});
--link-padding-y: var(--navbar-link-padding-y, #{$navbar-link-padding-y});
--link-main-color: var(--navbar-link-main-color, #{$navbar-link-main-color});
--link-hover-color: var(--navbar-link-hover-color, #{$navbar-link-hover-color});
--link-active-color: var(--navbar-link-active-color, #{$navbar-link-active-color});
--link-disabled-color: var(--navbar-link-disabled-color, #{$navbar-link-disabled-color});
--brand-padding-y: var(--navbar-brand-padding-y, #{$navbar-brand-padding-y});
--brand-margin-end: var(--navbar-brand-margin-end, #{$navbar-brand-margin-end});
@include map-font($navbar-brand-font, navbar-brand, brand);
--brand-fg-color: var(--navbar-brand-fg-color, #{$navbar-brand-fg-color});
--brand-hover-color: var(--navbar-brand-hover-color, #{$navbar-brand-hover-color});
--toggler-idle-bg-color: var(--navbar-toggler-idle-bg-color, #{$navbar-toggler-idle-bg-color});
--toggler-hover-bg-color: var(--navbar-toggler-hover-bg-color, #{$navbar-toggler-hover-bg-color});
--toggler-icon-size: var(--navbar-toggler-icon-size, #{$navbar-toggler-icon-size});
--toggler-icon-color: var(--navbar-toggler-icon-color, #{$navbar-toggler-icon-color});
--translucent-opacity: var(--navbar-translucent-opacity, #{$navbar-translucent-opacity});
--translucent-blur: var(--navbar-translucent-blur, #{$navbar-translucent-blur});
--translucent-saturation: var(--navbar-translucent-saturation, #{$navbar-translucent-saturation});
@if $navbar-link-font {
  @include map-font($navbar-link-font, navbar-link, link);
}

Sass variables

This component uses Sass variables in scss/config/_defaults.scss to define its defaults.

$navbar-padding-y:                    var(--space-xsmall);
$navbar-padding-x:                    0;
$navbar-fg-color:                     #{to-opacity(var(--fg-main), .65)};
$navbar-bg-color:                     var(--bg-main);

$navbar-nav-gap:                      0;

$navbar-link-padding-x:               var(--space-small);
$navbar-link-padding-y:               var(--space-xsmall);
$navbar-link-font:                    null;
$navbar-link-main-color:              $navbar-fg-color;
$navbar-link-hover-color:             #{to-opacity(var(--fg-main), .85)};
$navbar-link-active-color:            #{to-opacity(var(--fg-main), 1)};
$navbar-link-disabled-color:          #{to-opacity(var(--fg-main), var(--opacity-fg-slight))};

$navbar-brand-font:                   $font-text-xlarge-normal;
$navbar-brand-padding-y:              var(--space-2xsmall);
$navbar-brand-margin-end:             1rem;
$navbar-brand-fg-color:               var(--fg-main);
$navbar-brand-hover-color:            $navbar-brand-fg-color;

$navbar-toggler-idle-bg-color:        transparent;
$navbar-toggler-hover-bg-color:       var(--dim-slight);
$navbar-toggler-icon-color:           $navbar-fg-color;
$navbar-toggler-icon-size:            $icon-medium;

$navbar-translucent-opacity:          $translucent-opacity;
$navbar-translucent-blur:             var(--size-2xsmall);
$navbar-translucent-saturation:       $translucent-saturation;

Sass map

The global $breakpoints map is reassigned to $navbar-breakpoints in scss/_navbar.scss so the navbar's responsive expand/collapse classes can be configured independently of the framework's other breakpoint loops.

$navbar-breakpoints:                  $breakpoints;

Sass loops

Responsive .{breakpoint}:navbar-expand classes are generated by looping over $navbar-breakpoints.

// Generate series of responsive `.navbar-expand` classes for configuring
// where your navbar collapses and expands. Uses container queries so the
// navbar responds to its own width, not the viewport width.

// Mixin for expanded state styles (applied to descendants)
@mixin navbar-expanded {
  // Style the inner container since we can't style .navbar itself with container queries
  > [class*="container"] {
    flex-wrap: nowrap;
    justify-content: flex-start;
  }

  .navbar-nav {
    flex-direction: row;
  }

  .navbar-toggler {
    display: none !important; // stylelint-disable-line declaration-no-important
  }

  [class*="drawer"] {
    // stylelint-disable declaration-no-important
    // Reset native <dialog> UA styles and below-breakpoint drawer styles.
    // Must use !important to override both UA <dialog> defaults and the
    // responsive drawer styles from media-breakpoint-down().
    position: static !important;
    inset: auto !important;
    z-index: auto;
    display: flex !important;
    flex-grow: 1;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    max-height: none !important;
    padding: 0;
    margin: 0;
    visibility: visible !important;
    background-color: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    transform: none !important;
    @include transition(none);
    // stylelint-enable declaration-no-important

    .drawer-header {
      display: none !important; // stylelint-disable-line declaration-no-important
    }

    .drawer-body {
      display: flex;
      flex-grow: 1;
      flex-direction: row;
      align-items: center;
      padding: 0;
      overflow-y: visible;
    }
  }
}

// Always expanded (no responsive behavior)
.navbar-expand {
  @include navbar-expanded();

  // Also set on navbar itself for non-responsive case
  flex-wrap: nowrap;
  justify-content: flex-start;
}

// Responsive navbar expand classes using container queries
@include loop-breakpoints-down($navbar-breakpoints) using ($breakpoint, $next, $prefix) {
  @if $next {
    .#{$prefix}navbar-expand {
      @include container-breakpoint-up($next) {
        @include navbar-expanded();
      }
    }
  }
}