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
| Class | What it is |
|---|---|
navbar | The whole bar |
navbar-brand | The left part, always visible: logo and burger |
navbar-menu | The menu, hidden on narrow screens |
navbar-start, navbar-end | Groups of links at the left and right edges |
navbar-item | One 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.