Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

The navbar

A navbar is the horizontal navigation bar in the site header: logo, section links, a sign-in button. On narrow screens Bulma hides the links behind a three-line button, the burger. But Bulma cannot open the menu when the burger is clicked: your JavaScript does that, and it takes a few lines.

Parts of the bar

ClassWhat it is
navbarThe whole bar
navbar-brandThe left part, always visible: logo and burger
navbar-menuThe menu, hidden on narrow screens
navbar-start, navbar-endGroups of links at the left and right edges
navbar-itemOne item: a link, a button, an image

A bar for wide screens

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<nav class="navbar is-primary" aria-label="Main menu">
  <div class="navbar-brand">
    <a class="navbar-item has-text-weight-bold" href="/">Trattoria Oliva</a>
  </div>
  <div class="navbar-menu">
    <div class="navbar-start">
      <a class="navbar-item" href="#menu">Menu</a>
      <a class="navbar-item" href="#about">About</a>
    </div>
    <div class="navbar-end">
      <div class="navbar-item">
        <a class="button is-light" href="#booking">Book a table</a>
      </div>
    </div>
  </div>
</nav>

On a screen from 1024 px you see a turquoise bar: the name on the left, two links next to it, a button at the right edge. The preview is narrower than 1024 px, so it shows only the name: navbar-menu is hidden and there is nothing to open it with.

The burger and JavaScript

Add a burger to navbar-brand: a navbar-burger link with four empty <span> elements, from which CSS draws the lines. The data-target attribute holds the id of the menu the burger opens:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<nav class="navbar is-primary" aria-label="Main menu">
  <div class="navbar-brand">
    <a class="navbar-item has-text-weight-bold" href="/">Trattoria Oliva</a>
    <a role="button" class="navbar-burger" aria-label="Open menu" aria-expanded="false" data-target="mainMenu">
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
    </a>
  </div>
  <div id="mainMenu" class="navbar-menu">
    <div class="navbar-start">
      <a class="navbar-item" href="#menu">Menu</a>
      <a class="navbar-item" href="#about">About</a>
    </div>
  </div>
</nav>
 
<script>
  document.querySelectorAll('.navbar-burger').forEach((burger) => {
    burger.addEventListener('click', () => {
      const menu = document.getElementById(burger.dataset.target);
      const isOpen = burger.classList.toggle('is-active');
      menu.classList.toggle('is-active', isOpen);
      burger.setAttribute('aria-expanded', String(isOpen));
    });
  });
</script>

In a narrow preview three lines appear on the right. Click them: the lines turn into a cross and the list of links opens below. The whole mechanism is the is-active class: on the burger it draws the cross, on navbar-menu it shows the menu. The script sets this class on click and updates aria-expanded for screen readers.

A dropdown item

A navbar-item has-dropdown is-hoverable item opens a nested list on mouse hover — no JavaScript needed:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<nav class="navbar" aria-label="Main menu">
  <div class="navbar-menu is-active">
    <div class="navbar-start">
      <div class="navbar-item has-dropdown is-hoverable">
        <a class="navbar-link">Menu</a>
        <div class="navbar-dropdown">
          <a class="navbar-item" href="#starters">Starters</a>
          <a class="navbar-item" href="#pasta">Pasta</a>
          <hr class="navbar-divider">
          <a class="navbar-item" href="#wine">Wine list</a>
        </div>
      </div>
    </div>
  </div>
</nav>

The dropdown item goes into navbar-start in place of an ordinary link. The is-active class on navbar-menu is here only for the preview: the menu looks as if the burger has already been clicked, and the nested links are shown right under "Menu". On a wide screen the list appears under the "Menu" item with an arrow when you hover.

A fixed bar

The is-fixed-top modifier pins the bar to the top of the window while scrolling. So that it does not cover the start of the page, add the has-navbar-fixed-top class to the <body> tag — it adds top padding equal to the bar height.

Common mistake

Forgetting that data-target must match the menu's id. If you write data-target="menu" while the block has id="mainMenu", the script gets null, throws an error in the console, and the menu does not open. When the burger "does not work", check the data-target and id pair first.

Thanks for reading!

Donate to the site — we work hard for you.