When starting a new project, the styling we use is often one of the first considerations. I generally prefer to code my own SCSS, but often there in not time, and I reach for a CSS framework of some kind. I tend to prefer the utility systems like Tailwind or Bulma.
I enjoy using Bulma but it does not include JavaScript actions for menu toggle. So, the developer is left to find a solution. This article is an example of a simple way to use React hooks as an way to toggle a Navbar menu.
TLTR: Jump straight to the code and try it out, and you can take a look at the deployed Demo.
Setup
We are doing to set up a basic React App. My personal preference is to use my React Parcel Boilerplate using Parcel as a bundler. You can read the two part tutorial ARTICLE or view the Code of my Parcel Boilerplate.
However, in this tutorial, we will use Create React App, so we all are in a familiar environment to begin.
To start a new project with CRA, install as shown:
yarn create react-app react-bulma-navbar
or
npx create-react-app react-bulma-navbar
Clean up CRA
Next we are going to clean up the default setup. Delete the header section,<header> ... </header>
from App.js
, and replace with the following just to give us some content:
<h1>React Bulma Navbar Toggle</h1>
Delete the following files and their associated import statements:
- Delete
logo.svg
and the import statement inApp.js
- Delete
App.css
and the import statement inApp.js
- Delete
index.css
and the import statement inApp.js
Congratulations! You are the proud owner of an ugly site.
Add Bulma for Styling
Add Bulma to our project with yarn add bulma
or npm install --save bulma
. We will also need node-sass
as a Dev dependency: yarn add -D node-sass
or npm install --save-dev node-sass
.
Create in the src directory a file for our custom styles touch main.scss
, and in the new file, import bulma
: @import "~bulma/bulma";
. In App.js
add an import for our stylesheet: import 'main.scss'
Add Navbar
We are going to create a new functional component for our menu. As seen below, I have imported the default example from the Bulma web site, and trimmed some of the navigation out so we have just enough as an example:
import React from 'react'
export default function Navbar() {
return (
<nav className='navbar' role='navigation' aria-label='main navigation'>
<div className='navbar-brand'>
<a href='/' className='navbar-item'>
<img
src='https://bulma.io/images/bulma-logo.png'
alt='Logo'
width='112'
height='28'
/>
</a>
<a
role='button'
className={'navbar-burger burger'}
aria-label='menu'
aria-expanded='false'
data-target='navbarBasicExample'
>
<span aria-hidden='true'></span>
<span aria-hidden='true'></span>
<span aria-hidden='true'></span>
</a>
</div>
<div id='navbarBasicExample' className='navbar-menu'>
<div className='navbar-end'>
<div className='navbar-item'>
<a href='/' className='navbar-item'>
Home
</a>
<a href='/' className='navbar-item'>
Documentation
</a>
</div>
</div>
</div>
</nav>
)
}
Remember to add the import to App.js
:
import React from 'react'
import Navbar from './Navbar'
import './main.scss'
function App() {
return (
<div className='App'>
<Navbar />
<h1 className='container is-fluid'>React Bulma Navbar Toggle</h1>
</div>
)
}
export default App
If you start your development server it all will display nicely, but on the smaller screen sizes, the menu toggle does not work.
Add Navbar Toggle
There are a few ways to handle an event to toggle the menu on a click event. In a plain HTML project we could us VanillaJS to create a click handler with addEventListener()
, you can use JQuery, or you can use a pure CSS menu toggle.
In React there are a few options as well. You can create click handlers in a class Component. In our example, I have specifically chosen a functional component so we can utilize React Hooks.
So, first we need to create a custom Hook:
export default function Navbar() {
const [isActive, setisActive] = React.useState(false)
return (
...
)
}
Then add a click event to the Burger button, and ternary expressions to make the classes used dynamic and affected by the state. The new functional component looks like this:
export default function Navbar() {
const [isActive, setisActive] = React.useState(false)
return (
<nav className='navbar' role='navigation' aria-label='main navigation'>
<div className='navbar-brand'>
<a href='/' className='navbar-item'>
<img
src='https://bulma.io/images/bulma-logo.png'
alt='Logo'
width='112'
height='28'
/>
</a>
<a
onClick={() => {
setisActive(!isActive)
}}
role='button'
className={`navbar-burger burger ${isActive ? 'is-active' : ''}`}
aria-label='menu'
aria-expanded='false'
data-target='navbarBasicExample'
>
<span aria-hidden='true'></span>
<span aria-hidden='true'></span>
<span aria-hidden='true'></span>
</a>
</div>
<div id='navbarBasicExample' className={`navbar-menu ${isActive ? 'is-active' : ''}`}>
<div className='navbar-end'>
<div className='navbar-item'>
<a href='/' className='navbar-item'>
Home
</a>
<a href='/' className='navbar-item'>
Documentation
</a>
</div>
</div>
</div>
</nav>
)
}
What's next? Nothing you are done. When you click the menu toggle, the click handler, sets the state to the opposite of the current state. That is it.
Remember this is just the default example from Bulma. In a live site it would be helpful to use Link from React Router for the menu links, but this is a good basic start.
Top comments (7)
Awesome! Thank you, was super easy to follow. Also wanted to note, that this works with react-bulma-components too, tho Idk if it's improper to muddy up
<Navbar.Menu>
withI'm pretty new to React, so still using old tricks lol.
What a simple implementation! Awesome. I am a newbie in the world of ReactJS and Bulma with just the passion to create a simple website. While I knew I need to use state to implement the toggle feature, I wasn't sure where to start. Using hooks to do thiis is very simple and effective. Thank You!!
Awesome guide, was super easy to follow and a great implementation!
Thank you. I am glad you found it helpful.
Thanks for this Chuck, this has helped me in completing my website project for a client. Things aren't always as easy as using Bootstrap!
Thank you for the response and I am glad it helped you out.