I'm trying to use hamburger menu on bulma css, but it doesn't work. What is wrong?
Asked Answered
F

12

28

I'm new on bulma css http://bulma.io/

I'm trying to use hamburger menu for mobile user. I just followed instruction on this page: http://bulma.io/documentation/components/nav/

But it doesn't work. What should I add ?

Actually, I can see hamburger menu, but it doesn't work when I am click it.

Thank you.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
        <title>test</title>

        <link rel="stylesheet" href="css/bulma.min.css">
        <link rel="stylesheet" href="css/custom.css">
    </head>
    <body>
        <section class="hero is-fullheight is-primary is-bold">
            <!-- Hero header: will stick at the top -->
            <div class="hero-head">
                <header class="nav">
                    <div class="container">
                        <div class="nav-left">
                            <a class="nav-item" href="/">
                                <img src="img/logo.png" alt="Logo">
                            </a>
                        </div>
                        <span class="nav-toggle">
                            <span></span>
                            <span></span>
                            <span></span>
                        </span>
                        <div class="nav-right nav-menu">
                            <a class="nav-item" href="/about">
                                About
                            </a>
                            <a class="nav-item" href="/path">
                                Path
                            </a>
                            <a class="nav-item" href="/blog">
                                Blog
                            </a>
                        </div>
                    </div>
                </header>
            </div>
            <!-- Hero content: will be in the middle -->
            <div class="hero-body">
                <div class="container has-text-centered">
                </div>
            </div>
        </section>
    </body>
</html>
Fi answered 14/12, 2016 at 7:35 Comment(2)
This should work just out of the box for bulma css. Please check if you have the minified css file at the correct path. You may also use the CDN option. CDN link for bulma is here.Angelineangelique
Umm, I'm sure this is the correct path. In addition, I also tried to CDN, it didn't work for me.Fi
B
10

This may be an issue with the example given in the docs, I was able to get it working by adding ids to the .nav-toggle and .nav-menu.

<span id="nav-toggle" class="nav-toggle"> and <div id='nav-menu' class="nav-right nav-menu">

jsfiddle here.

So to get the example working, you'd have to add 'id's to the respective elements. I'd recommend deep diving into the docs though

Butz answered 14/12, 2016 at 7:56 Comment(5)
I tried it already, but it didn't work. The thing what I would like to know is the file I should import is only bulma.css ? I mean I thought I should import jquery or something.Fi
well.. you should import jquery and the bulma.js . the click events for the nav are in bulma.jsButz
Finally, it works!! Thanks a lot. I was misunderstanding that bulma css is working only cssFi
I did it! Thank you very much:)Fi
A pity that your example relies on jQuery.Cochrane
V
41

This solution uses Vue.js to toggle the bulma nav component when viewing on mobile. I hope this helps others that are looking for an alternative solution.

JS

First, I add the cdn for Vue.js which can be found here https://unpkg.com/vue, and include an instance of Vue in the javascript.

new Vue({
  el: '#app',
  data: {
    showNav: false
  }
});

HTML

a. Wrap the nav section with the element "app" to make it reactive (this maps to the "el" property of the Vue instance).

<div id="app"> ... </div>

b. Update .navbar-burger using the v-on: directive to listen for the click event and toggle the data property showNav.

<div class="navbar-burger" v-on:click="showNav = !showNav" v-bind:class="{ 'is-active' : showNav }">

c. Update .navbar-menu using the v-bind: directive to reactively update the class attribute with the result of the showNav property.

<div class="navbar-menu" v-bind:class="{ 'is-active' : showNav }">

Solution

I've included the entire solution in this jsfiddle

Vitiate answered 2/7, 2017 at 4:33 Comment(5)
came here from google and wanted to add to your answer since nav will be deprecated soon on Bulma. If you are using the navbar example just need to add :class="{ 'is-active': showNav }" @click="showNav = !showNav" to the navbar-burger tag and also :class="{ 'is-active': showNav }" to the navbar-menuScorpio
Thank you @JeffBeltran! I've updated my solution to use the latest version of bulma.css and the navbar component.Vitiate
Can you add to your solution to make the navbar slide down when it's clicked? I've tried adding a transition wrapper around navbar-menu but can't seem to make it work.Course
@Course I've looked at trying to add this, but only found that you cannot apply a transition to elements that have display: none. CSS is not my strong suit and so hopefully somebody else could offer a solution.Vitiate
thanks for this answer. Using it I was able to adapte the logic for angular, which I have posted below.Leola
B
10

This may be an issue with the example given in the docs, I was able to get it working by adding ids to the .nav-toggle and .nav-menu.

<span id="nav-toggle" class="nav-toggle"> and <div id='nav-menu' class="nav-right nav-menu">

jsfiddle here.

So to get the example working, you'd have to add 'id's to the respective elements. I'd recommend deep diving into the docs though

Butz answered 14/12, 2016 at 7:56 Comment(5)
I tried it already, but it didn't work. The thing what I would like to know is the file I should import is only bulma.css ? I mean I thought I should import jquery or something.Fi
well.. you should import jquery and the bulma.js . the click events for the nav are in bulma.jsButz
Finally, it works!! Thanks a lot. I was misunderstanding that bulma css is working only cssFi
I did it! Thank you very much:)Fi
A pity that your example relies on jQuery.Cochrane
K
6
(function() {
    var burger = document.querySelector('.nav-toggle');
    var menu = document.querySelector('.nav-menu');
    burger.addEventListener('click', function() {
        burger.classList.toggle('is-active');
        menu.classList.toggle('is-active');
    });
})();
Krug answered 4/7, 2017 at 5:12 Comment(3)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Townes
Oh i'm sorry, just starting to help people around here... so i'll try to explain for anyone(thinking about long term): We need to query(remember jQuery? no need to use it anymore) the nav-toogle and nav-menu, store them in variables(read about reference type), after that start to listen to events on the "burger" in this case, a mouse click or touch on the screen. When the click happens it'll toggle the class 'is-active'. this function is a self executing function, what means it is executing from the moment the page is loaded.Krug
@RuggeroRebellato: why use an immediately invoked functionaly expression (IIFE)? Will its use allow this functionality as soon as the page loaded? In that case, why not just use the onLoad/load event listener?Overfill
P
3

You can get it to work without using jquery or bulma.js. Just simply use your own javascript to add is-active to nav-menu class on click on nav-toggle.

nav-menu is collapsed.

nav-menu is-active is expanded.

I thought someome might be looking for a solution without jquery so there will be everything in one place.

Poor answered 24/12, 2016 at 18:21 Comment(0)
A
3

To make the toggle click event work, just add the below js code. You may create a JS folder, then bulma.js file.

// source: https://gist.github.com/Bradcomp/a9ef2ef322a8e8017443b626208999c1
(function () {
    var burger = document.querySelector('.burger');
    var menu = document.querySelector('#' + burger.dataset.target);
    burger.addEventListener('click', function () {
        burger.classList.toggle('is-active');
        menu.classList.toggle('is-active');
    });
})();
At the end of your html page add the script. ex:
<script async type="text/javascript" src="./js/bulma.js"></script>
Aleshia answered 9/11, 2018 at 4:58 Comment(0)
T
3

The bulma package does not provide any javascript. So you have to write it yourself. But you do not need anything fancy. Just make the id of toggled element and the data-target of the burger be the same. Something like this:

<a role="button" class="navbar-burger" data-target="navMenu" aria-label="menu" aria-expanded="false">
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
</a>

<div class="navbar-menu" id="navMenu">
  <!-- navbar-start, navbar-end... -->
</div>

And add this javascript snippet into end of your file(note: you do not have to change anything):

<script>
  document.addEventListener('DOMContentLoaded', () => {

    // Get all "navbar-burger" elements                                                              
   const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);

    // Check if there are any navbar burgers
    if ($navbarBurgers.length > 0) {

      // Add a click event on each of them
      $navbarBurgers.forEach( el => {
        el.addEventListener('click', () => {

          // Get the target from the "data-target" attribute
          const target = el.dataset.target;
          const $target = document.getElementById(target);
 
          // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
          el.classList.toggle('is-active');
          $target.classList.toggle('is-active');
  
        });
      });
    }  

  });
</script>

And that is it! It works!

These codeblocks has been taken from documentation: https://bulma.io/documentation/components/navbar/#navbar-burger

Toxic answered 15/9, 2020 at 17:16 Comment(1)
It works, but there is a typo, it should be '.navbar-burger' not '.navbar- burger'Baillieu
G
2

There is an easier way! Before I get to that, it looks like there are a few problems with your Html.

First issue. You don't have the navbar structure set up like the documentation suggests. If you replace the nav-left with navbar-brand it will take care of some of your Html for you. In your code example, you have your logo as a nav-item inside of a nav-left. navbar-brand does exactly that. What you've done here may work but, I'm not sure exactly what that would do. From the documentation:

"navbar-brand the left side, always visible, which usually contains the logo and optionally some links or icons"

So if you take that out to the level of the of the container and within that, you can just put your logo inside the first navbar-item. Next thing is to pull the 'navbar-burgerinside of thenavbar-brand`.

"The navbar-burger is a hamburger menu that only appears on mobile. It has to appear as the last child of navbar-brand."

Once that is set up you'll want to put the menu items you wish to collapse inside of the navbar-menu. This container should be a sibling of the navbar-brand so they should be on the same level together. So your code (within your container div) should look something LIKE SO:

<nav class="navbar">
    <div class="navbar-brand">
      <a class="navbar-item" href="/">
        <img src="../assets/icon.png" alt="something">
      </a>

      <div class="navbar-burger burger" data-target="Options">
        <span></span>
        <span></span>
        <span></span>
      </div>
    </div>

    <div class="navbar-menu" id="Options">
      <div class="navbar-end">
        <a class="nav-item" href="/about">About</a>
        <a class="nav-item" href="/path">Path</a>
        <a class="nav-item" href="/blog">Blog</a>
      </div>
    </div>
  </nav>

The final piece to the puzzle is: you gotta set the data-target of your burger to the the id of the navbar-menu. It's not very clear that's what they are talking about in the docs. Whatever the case, after you make those changes, the javascript code from the documentation should work!

I realize that this question was asked many moons ago but I hope this can help SOMEONE.

Bulma Docs http://bulma.io/documentation/components/navbar/

Gracielagracile answered 24/7, 2017 at 19:22 Comment(2)
Unfortunately, it doesn't, because it doesn't seem to work even with this. I'm afraid there's just something wrong with Bulma itself.Shaum
@Shaum Hmmm, mine works with just the changes above. Another issue I found when I was working on this: I hadn't set my viewport meta field in the HTML header. If you don't have the viewport set, none of the built in responsiveness will work. Try adding this to the header of your html file: html <meta name="viewport" content="width=device-width, initial-scale=1.0"> I'd have to see your code to really help you though.Gracielagracile
A
2

My simple but functional answer:

function toggleBurger() {
    var burger = $('.burger');
    var menu = $('.navbar-menu');
    burger.toggleClass('is-active');
    menu.toggleClass('is-active');
}

And in the burger tag:

<div class="navbar-burger burger" data-target="navMenu" onclick="toggleBurger()">
            <span></span>
            <span></span>
            <span></span>
        </div>
Abrams answered 11/12, 2017 at 16:14 Comment(0)
L
2

Here is an angular solution:

template - button (notice the last two lines)

<a
    role="button"
    class="navbar-burger burger"
    aria-label="menu"
    aria-expanded="false"
    data-target="navbarBasicExample"
    [class.is-active]="showBurgerMenu"
    (click)="showBurgerMenu = !showBurgerMenu">

template - menu (notice the last line)

<div 
    id="navbarBasicExample" 
    class="navbar-menu" 
    [class.is-active]="showBurgerMenu">

component (notice the showBurgerMenu property)

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'app-navbar',
    templateUrl: './navbar.component.html',
    styleUrls: ['./navbar.component.sass']
})
export class NavbarComponent {
    showBurgerMenu: boolean;
    constructor() {}

}
Leola answered 8/4, 2019 at 7:41 Comment(0)
F
2

you can also make it work with an inline onclick

<a role="button" onclick="this.classList.toggle('is-active');document.querySelector('#'+this.dataset.target).classList.toggle('is-active');" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="efpnavbar">
Fascine answered 14/8, 2022 at 3:23 Comment(1)
Yes, thank you for making sense out of all the unnecessarily over-complicated examples and "solutions" here... Just remember to change data-target to what you're using.Barthelemy
N
0

I had the same problem with Vue.js and I solved it like this :

<span class="navbar-burger burger" data-target="navbarMenu" @click="show()">
                        <span></span>
                        <span></span>
                        <span></span>
                    </span>
                </div>
                <div id="navbarMenu" class="navbar-menu">
                    <div class="navbar-end">
                        <div class="tabs is-right">
                            <ul>
                                <li><a>Home</a></li>
                                <li><a href="">Examples</a></li>
                                <li><a href="">Features</a></li>
                                <li><a href="">Team</a></li>
                                <li><a href="">Help</a></li>
                            </ul>
                        </div>
                    </div>
                </div> </span>

then I added this code in methods section :

methods:{
show()
{
  var burger = document.querySelector('.burger');
  var menu = document.querySelector('.navbar-menu');
  burger.classList.toggle('is-active');
  menu.classList.toggle('is-active');
}}

I hope this code helps someone .

Nomanomad answered 22/10, 2021 at 11:30 Comment(0)
D
0

If you use SCSS and i.e. purge-css for your project, make sure the .is-active class is not stripped out by your css-purging...

For me then the vanilla example worked:

JS:

document.addEventListener("DOMContentLoaded", () => {
  // Get all "navbar-burger" elements
  const $navbarBurgers = Array.prototype.slice.call(
    document.querySelectorAll(".navbar-burger"),
    0
  );

  // Add a click event on each of them
  $navbarBurgers.forEach((el) => {
    el.addEventListener("click", () => {
      // Get the target from the "data-target" attribute
      const target = el.dataset.target;
      const $target = document.getElementById(target);

      // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
      el.classList.toggle("is-active");
      $target.classList.toggle("is-active");
    });
  });
});

and HTML:

<nav class="navbar headnavi is-fixed-top" role="navigation" aria-label="main navigation">
  <div class="navbar-brand">
    <a class="navbar-item" href="{{ site.url }}">
      <span class="is-size-3 is-size-5-mobile has-text-weight-semibold ml-2">{{ site.name }}</span>
    </a>

    <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="top">
      <span aria-hidden="true" class="nav-toggle" ></span>
      <span aria-hidden="true" class="nav-toggle" ></span>
      <span aria-hidden="true" class="nav-toggle" ></span>
    </a>
  </div>

  <div id="top" class="navbar-menu">
    <div class="navbar-start">
    </div>

    <div class="navbar-end">
    <a class="navbar-item">
        Home
      </a>
    
      <a class="navbar-item">
        Documentation
      </a>
    
      <div class="navbar-item has-dropdown is-hoverable">
        <a class="navbar-link" href="/">
          More
        </a>
    
        <div class="navbar-dropdown is-right">
          <a class="navbar-item">
            About
          </a>
          <a class="navbar-item">
            Jobs
          </a>
          <a class="navbar-item">
            Contact
          </a>
          <hr class="navbar-divider">
          <a class="navbar-item">
            Report an issue
          </a>
        </div>
      </div>
      <div class="navbar-item">
        <div class="buttons">
        </div>
      </div>
    </div>
  </div>
</nav>
Dominickdominie answered 17/1, 2023 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.