Navigation Navbar

Navbar

Responsive navbar with brand, plain links, dropdown groups, full-width mega menus, and a slide-in mobile drawer. Auto-initialized on data-wf-navbar with a configurable breakpoint. Supports dark, primary, and transparent color themes, and sticky positioning.

Quick Start

The minimal structure is nav.wf-navbar[data-wf-navbar]div.wf-navbar-inner containing a brand, a hamburger toggle, and a div.wf-navbar-menu[data-wf-navbar-menu] that holds wf-navbar-start and wf-navbar-end sections. Click the Products link below to see the dropdown.

HTML
<nav class="wf-navbar" data-wf-navbar>
  <div class="wf-navbar-inner">

    <!-- Brand -->
    <a class="wf-navbar-brand" href="/">
      <div class="wf-navbar-brand-logo"><i class="icon wojo" aria-hidden="true"></i></div>
      Wojo
    </a>

    <!-- Mobile hamburger -->
    <button class="wf-navbar-hamburger" data-wf-navbar-toggle
            aria-expanded="false" aria-label="Open menu">
      <i class="icon menu" aria-hidden="true"></i>
    </button>

    <!-- Drawer -->
    <div class="wf-navbar-menu" data-wf-navbar-menu>

      <!-- Mobile-only drawer header -->
      <div class="wf-navbar-menu-header">
        <a class="wf-navbar-brand" href="/">...</a>
        <button class="wf-navbar-hamburger" data-wf-navbar-toggle aria-expanded="false"
                aria-label="Close menu">
          <i class="icon cancel" aria-hidden="true"></i>
        </button>
      </div>

      <!-- Left items -->
      <div class="wf-navbar-start">
        <a class="wf-navbar-item" href="/" aria-current="page">Home</a>
        <a class="wf-navbar-item" href="/features">Features</a>
      </div>

      <!-- Right items -->
      <div class="wf-navbar-end">
        <a class="wf-navbar-item" href="/login">Sign in</a>
        <a class="wf-btn wf-btn-sm" href="/signup">Get started</a>
      </div>

    </div>
  </div>
</nav>

Dropdown Group

Wrap a trigger button and a div.wf-navbar-dropdown in a div.wf-navbar-group[data-wf-navbar-group] . The script toggles an is-open class on the group and sets aria-expanded on the trigger. On desktop the dropdown is absolutely positioned below the trigger; on mobile it expands inline via a max-height transition. Add wf-navbar-chevron to a chevron icon inside the trigger to rotate it when open. The script auto-flips to wf-navbar-group--end (right-aligned panel) when the default left-aligned position would overflow the viewport.

HTML
<div class="wf-navbar-group" data-wf-navbar-group>

  <!-- Trigger -->
  <button class="wf-navbar-item" aria-expanded="false">
    Company
    <i class="icon chevron down wf-navbar-chevron" aria-hidden="true"></i>
  </button>

  <!-- Panel -->
  <div class="wf-navbar-dropdown">
    <div>
      <a class="wf-navbar-dd-item" href="/about">
        <i class="icon user" aria-hidden="true"></i> About
      </a>
      <a class="wf-navbar-dd-item" href="/blog">
        <i class="icon mail" aria-hidden="true"></i> Blog
      </a>
      <hr class="wf-navbar-dd-divider">
      <a class="wf-navbar-dd-item wf-active" href="/contact">Contact</a>
    </div>
  </div>

</div>

Mega Menu

Replace wf-navbar-dropdown with wf-navbar-mega and add wf-navbar-group--mega to the group to make a full-width panel that spans the entire navbar. Inside the panel, use wf-navbar-mega-inner as a centred grid container, wf-navbar-mega-col for each column, and wf-navbar-mega-item for each link. Each item can include an icon container ( wf-navbar-mega-icon ) and a text block ( wf-navbar-mega-content ) with a title and description. Add wf-navbar-mega-col--feature to give a column a subtle highlighted background. On mobile the mega panel collapses inline like a dropdown.

HTML
<div class="wf-navbar-group wf-navbar-group--mega" data-wf-navbar-group>

  <button class="wf-navbar-item" aria-expanded="false">
    Solutions
    <i class="icon chevron down wf-navbar-chevron" aria-hidden="true"></i>
  </button>

  <div class="wf-navbar-mega">
    <div class="wf-navbar-mega-inner">

      <!-- Regular column -->
      <div class="wf-navbar-mega-col">
        <p class="wf-navbar-mega-label">Platform</p>
        <a class="wf-navbar-mega-item" href="/analytics">
          <div class="wf-navbar-mega-icon">
            <i class="icon chart bar" aria-hidden="true"></i>
          </div>
          <div class="wf-navbar-mega-content">
            <span class="wf-navbar-mega-title">Analytics</span>
            <span class="wf-navbar-mega-desc">Real-time data & insights</span>
          </div>
        </a>
        <a class="wf-navbar-mega-item" href="/reports">
          <div class="wf-navbar-mega-icon">
            <i class="icon file text" aria-hidden="true"></i>
          </div>
          <div class="wf-navbar-mega-content">
            <span class="wf-navbar-mega-title">Reports</span>
            <span class="wf-navbar-mega-desc">Scheduled & ad-hoc reports</span>
          </div>
        </a>
      </div>

      <!-- Highlighted feature column (hidden on mobile) -->
      <div class="wf-navbar-mega-col wf-navbar-mega-col--feature">
        <p class="wf-navbar-mega-label">What’s new</p>
        <a class="wf-navbar-mega-item" href="/changelog">
          <div class="wf-navbar-mega-content">
            <span class="wf-navbar-mega-title">Changelog</span>
            <span class="wf-navbar-mega-desc">Latest releases</span>
          </div>
        </a>
      </div>

    </div>
  </div>

</div>

Mobile Drawer

Below the breakpoint (default 768 px) the hamburger button appears and the wf-navbar-menu becomes a fixed, slide-in side drawer. The hamburger button carries data-wf-navbar-toggle ; place a second one inside wf-navbar-menu-header as a close button. The script appends a wf-navbar-backdrop to <body> while the drawer is open — clicking the backdrop closes the drawer. Opening the menu also swaps the hamburger icon to a cancel icon automatically.

HTML
<!-- Hamburger (inside wf-navbar-inner, hidden on desktop) -->
<button class="wf-navbar-hamburger"
        data-wf-navbar-toggle
        aria-expanded="false"
        aria-label="Open menu">
  <i class="icon menu" aria-hidden="true"></i>
</button>

<!-- Slide-in drawer -->
<div class="wf-navbar-menu" data-wf-navbar-menu>

  <!-- Sticky header inside the drawer -->
  <div class="wf-navbar-menu-header">
    <a class="wf-navbar-brand" href="#">Brand</a>
    <button class="wf-navbar-hamburger" data-wf-navbar-toggle aria-label="Close menu">
      <i class="icon cancel" aria-hidden="true"></i>
    </button>
  </div>

  <div class="wf-navbar-start">
    <!-- nav items, groups, etc. -->
  </div>
  <div class="wf-navbar-end">
    <!-- actions, sign-in, etc. -->
  </div>

</div>

<!-- Backdrop is injected by the script; no markup needed -->

Themes

Three built-in color themes are available as modifier classes on the wf-navbar root element. The default theme inherits --wf-surface as its background. All theme modifiers work by overriding the CSS custom properties on the root, so they automatically apply to all nested panels, items, and the mobile drawer.

HTML
<!-- Dark -->
<nav class="wf-navbar wf-navbar--dark" data-wf-navbar>...</nav>

<!-- Primary (brand color) -->
<nav class="wf-navbar wf-navbar--primary" data-wf-navbar>...</nav>

<!-- Transparent (no background or bottom border) -->
<nav class="wf-navbar wf-navbar--transparent" data-wf-navbar>...</nav>

Sticky

Add wf-navbar--sticky to pin the navbar to the top of the viewport using position: sticky; top: 0 . It combines with any theme modifier class.

HTML
<nav class="wf-navbar wf-navbar--sticky" data-wf-navbar>
  ...
</nav>

Data Attributes

All configuration is handled through HTML data attributes placed on the relevant elements. No JavaScript options object is required for typical usage.

Attribute Element Description
data-wf-navbar <nav> Initializes the component on this element.
data-wf-navbar-menu .wf-navbar-menu Marks the slide-in drawer so the script can open/close it.
data-wf-navbar-toggle .wf-navbar-hamburger Marks a button as a mobile drawer toggle. Can appear on multiple buttons (e.g., the top hamburger and the in-drawer close button).
data-wf-navbar-group .wf-navbar-group Marks a container as a dropdown/mega group. The script toggles is-open on this element.
data-wf-navbar-breakpoint [data-wf-navbar] Mobile breakpoint in pixels. Default: 768. Override with e.g. data-wf-navbar-breakpoint="1024".

CSS Properties

All token overrides are scoped to .wf-navbar so multiple navbars on the same page can have independent themes.

Property Default Description
--wf-nbar-bg var(--wf-surface) Background color of the navbar and its panels.
--wf-nbar-border var(--wf-border) color used for the bottom border and panel borders.
--wf-nbar-text var(--wf-text) Default text color for items and brands.
--wf-nbar-muted var(--wf-text-muted) Muted text color used for mega column labels and chevrons.
--wf-nbar-accent var(--primary-color) Accent color used for mega item icons.
--wf-nbar-height 3.5rem Height of the inner row and the mobile drawer header.
--wf-nbar-item-hover var(--primary-color-inverted) Background color applied on item hover.
--wf-nbar-active-text var(--primary-color) Text color for .wf-active and [aria-current=page] items.
--wf-nbar-dd-shadow 0 2px 8px … 0 8px 24px … Box shadow applied to dropdown and mega panels.
--wf-nbar-dd-radius var(--wf-radius-5) Border radius for dropdown panels and the navbar root.
--wf-nbar-z 900 Z-index of the navbar. Backdrop is z - 2, mobile drawer is z - 1.
--wf-nbar-speed .18s Transition duration for open/close animations and hover states.
--wf-nbar-ease cubic-bezier(.4, 0, .2, 1) Easing function for open/close transitions.

Programmatic API

Each initialized navbar exposes an instance on el._wfNavbar . All methods can also be called on a manually created instance.

Method Description
openMobile() Open the mobile slide-in drawer. No-op if already open.
closeMobile() Close the mobile drawer and remove the backdrop. No-op if already closed.
closeAll() Close all open dropdown and mega-menu groups.
destroy() Remove all event listeners, close the mobile drawer, and remove the instance reference from the element.
JS
// Auto-init instance (set during DOMContentLoaded)
const nav = document.querySelector('[data-wf-navbar]')._wfNavbar

nav.openMobile()
nav.closeMobile()
nav.closeAll()
nav.destroy()

// Manual init
import { WojoNavbar } from '/assets/js/wf-production.min.js'

const instance = new WojoNavbar(nav, { breakpoint: 1024 }).init()

Events

All events are dispatched on the navbar root element and bubble normally. Group events include the group element in event.detail .

Event Detail Description
wf:navbar-open { group } Fired when a dropdown or mega group opens.
wf:navbar-close { group } Fired when a dropdown or mega group closes.
wf:navbar-mobile-open Fired when the mobile slide-in drawer opens.
wf:navbar-mobile-close Fired when the mobile slide-in drawer closes.
JS
const nav = document.querySelector('[data-wf-navbar]')

nav.addEventListener('wf:navbar-open', e => {
  console.log('Group opened:', e.detail.group)
})

nav.addEventListener('wf:navbar-mobile-open', () => {
  document.body.classList.add('no-scroll')
})

nav.addEventListener('wf:navbar-mobile-close', () => {
  document.body.classList.remove('no-scroll')
})

Class Reference

All modifier classes available on .wf-navbar

Class Description
wf-navbar Root navbar element. Defines all CSS custom properties.
wf-navbar--dark Dark background theme modifier.
wf-navbar--primary Primary (brand) color theme modifier.
wf-navbar--transparent Removes the background and bottom border.
wf-navbar--sticky Pins the navbar to the top of the viewport (position: sticky).
wf-navbar-inner Flex row inside the navbar that holds brand, hamburger, and menu.
wf-navbar-brand Brand/logo link. Also used as the title inside the mobile drawer header.
wf-navbar-brand-logo Square icon box element placed inside the brand link.
wf-navbar-hamburger Hamburger / close toggle button. Hidden on desktop, visible on mobile.
wf-navbar-menu Slide-in drawer wrapper on mobile; flex row on desktop.
wf-navbar-menu-header Sticky header shown at the top of the mobile drawer. Hidden on desktop.
wf-navbar-start Left-aligned section for navigation links and groups.
wf-navbar-end Right-aligned (auto-margin) section for sign-in links and action buttons.
wf-navbar-item A nav link or group trigger button. Apply wf-active or aria-current="page" for the active state.
wf-navbar-chevron Icon inside a group trigger that rotates 180° when the group is open.
wf-navbar-group Dropdown group wrapper. Add data-wf-navbar-group to activate.
wf-navbar-group--end Right-aligns the dropdown panel. Auto-applied by JS when left-aligned would overflow; can be set manually.
wf-navbar-group--mega Makes the group use a full-width mega panel instead of a dropdown.
wf-navbar-dropdown Absolutely positioned dropdown panel. Contains a single <div> flex column.
wf-navbar-dd-item Link row inside a dropdown panel. Add wf-active to highlight the current page.
wf-navbar-dd-divider Horizontal rule divider between dropdown items. Hidden on mobile.
wf-navbar-mega Full-width mega panel. Spans the full width of the navbar on desktop.
wf-navbar-mega-inner Centred auto-fit grid container inside the mega panel.
wf-navbar-mega-col Single column inside the mega grid.
wf-navbar-mega-col--feature Highlighted column variant with a subtle surface background. Hidden on mobile.
wf-navbar-mega-label Small all-caps column heading inside a mega column.
wf-navbar-mega-item Link row inside a mega column. Typically, contains an icon and content block.
wf-navbar-mega-icon Square icon container inside a mega item.
wf-navbar-mega-content Text wrapper inside a mega item, containing a title and description.
wf-navbar-mega-title Bold item title inside wf-navbar-mega-content.
wf-navbar-mega-desc Muted description line inside wf-navbar-mega-content.
wf-navbar-backdrop Blurred overlay injected into <body> by JS while the mobile drawer is open.
is-open State class added by JS to [data-wf-navbar-group] when open, and to .wf-navbar-menu when the mobile drawer is open.
is-visible State class added by JS to .wf-navbar-backdrop to trigger the fade-in transition.
Show More