Sliding menus are all the rage in UIs today. All the cool kids are building them, and your friends probably just can’t get enough of them. These menus are basically off-screen elements that slide into view when you click or tap on something. That something could be an arrow, a hamburger icon, or something else that indicates a menu will appear.
To see a sliding menu in action, go here: https://www.kirupa.com/react/examples/slidingmenu_css/index.html.
You’ll see a yellow menu with some navigation links smoothly slide in. If you click a navigation link or anywhere in the yellow region inside that menu, the menu slides back (really smoothly again, of course) and the content behind it reappears. Let’s look at how to create all of this using React.
Note: For a Non-React Solution
Before we jump into the code, let’s take a few moments to better understand how exactly our sliding menu works. Starting at the very top, we have our page that displays some content:
When you decide to bring up the menu (by clicking/tapping the blue circle in our example), the menu magically slides into view:
The way this sliding menu works isn’t as crazy as it seems. The menu is never truly nonexistent; it is simply hidden outside the view. To see what that looks like, check out the following diagram:
Just to the left of the content what we see is our menu, patiently hiding until it is called upon. We do that by shifting the menu as far left as we can until it’s fully out of view. Figuring out how far to shift is easy. Our menu’s size is the same as our browser’s window (a.k.a. the viewport) size because we want the menu to fully cover up whatever is shown. Given that detail, we just shift the menu left by the browser’s width. One way of doing that might be by using some CSS that looks as follows:
We set our menu’s position to
fixed. This single change gives our menu a whole lot of magical capabilities. For starters, it ensures that normal layout rules no longer apply to it. We can position our menu anywhere we want using normal x and y values, and the menu won’t shift away from where we have it positioned. If that isn’t awesome enough, our menu won’t even display a scrollbar if we happen to hide it somewhere offscreen.
All this is a good thing because we hide our menu offscreen by setting our menu’s left and top properties to
0 and setting our menu’s transform property to a
translate3d method with a horizontal value of
-100vw. The negative value ensures that we shift the menu left by the amount equivalent to our browser window’s width. While not directly related to position, the size of our menu plays an important role as well. That’s why, in this CSS snippet, we have the
height properties set with values of
100vh, respectively, to ensure that our menu’s size is the same as our browser window’s size.
What Are These vw and vh Units?
If you’ve never seen the vw and vh units, they stand for viewport width (vw) and viewport height (vh). They’re a bit similar to percentage values. Each unit is 1/100th the width or height of your viewport (what we’ve been simply calling the browser window). For example, a value of 100vw means that its value is the full width of our browser window. Similarly, 100vh refers to a value that is the full height of our browser window.
When the menu is called upon to slide into view, we slide the menu right until its horizontal position is the same as our browser window origin. If we had to look at what the CSS for it might look like, this would be an easy change from what we already have. We simply set our
translate3d method and set the horizontal position to a value of
That might look something like this:
This change ensures that our menu is shifted right from being hidden offscreen (with a horizontal translate value of
-100vw) and is now visible. When our menu needs to disappear, we can translate it back:
The biggest thing we haven’t spoken about is the animation that makes the sliding look cool. This is done using a simple CSS transition that animates the
If you’re not familiar with CSS transitions, it’s a very simple concept to wrap your brain around. I don’t explain it here, so take a few moments and read through the short Introduction to CSS Transitions article (https://www.kirupa.com/html5/introduction_css_transitions.htm) for an overview.
So far, we’ve taken a bird’s-eye view of how our sliding menu works. A few details need to be looked at, but we’ll do that in the next couple sections when we actually build this menu.
Now that you have a basic idea about how a sliding menu works, let’s turn all that theoretical knowledge into some sweet JSX and code. The first thing we’re going to do is look at our example in terms of the individual components that will make it up.
At the very top, we have our
This component is responsible for doing nonvisual things like managing state, hosting our
MenuButton components, and displaying some of the initial text. The bird’s-eye view looks a bit like this:
In the next few sections, we’ll start creating these components and getting the example up and running.
create-react-app to create a new project called
slidingmenu. If you aren’t familiar with how to do that, check out Chapter 13, “Setting Up Your React Dev Environment Easily,” to walk through the details of creating and working with React projects. After you’ve created your project, you want to start from a blank slate. Delete everything in your
src folders. You’ll re-create the necessary pieces shortly.
Let’s start by creating our HTML document. In your
public folder, create a file called
index.html. Inside it, add the following contents:
This HTML page is simply the destination where all of our React components will eventually render their output.
Next, you want to create a file called
index.js in the
src folder that will be responsible for teeing things up in the code. Add the following content into this file:
render call here is responsible for displaying the output of our
MenuContainer component into the
div element we specified in HTML a few moments ago. In our
import statements, besides pulling in the
react-dom libraries, we are referencing
index.css and our
MenuContainer component. That’s all there is to our
Next we’re going to create the
index.css file in our
src folder and get the page’s basic styling defined. In this file, add the following two style rules:
There isn’t much to say about these style rules, so the last thing we do to get our initial app set up is create our
MenuContainer component. Create a file called
MenuContainer.js in the
src folder and add the following JS and JSX into it:
Be sure to save the changes you made to all of your files, and test your app (using
npm start) to ensure that your initial setup of the app works fine. If everything worked out properly, your default browser will launch and you’ll see something that looks as follows:
There’s no menu to slide or button to press; we’ll add both of those in the next couple sections.
With the initial setup out of the way, it’s time for the fun part: actually building the menu. Our menu is shown or hidden as follows:
1. When you click a button, the menu slides into view.
2. When you click anywhere on the menu, the menu slides out of view.
This means that we need to account for a few things going on. We need to maintain some state to keep track of whether the menu is hidden or shown. This state needs to be something we update from both the button and the menu because clicking on either will toggle whether the menu is visible. We need our state to live in a common location that both the menu and the button can access. That common location will be inside our
MenuContainer component, so let’s add the code relating to our state logic.
MenuContainer.js file, add the constructor and
toggleMenu methods just above our
The code you’ve just added should look like a walk in the park by now. You’re storing a variable called
visible in your state object, and you’re creating a method called
toggleMenu that will be responsible for toggling whether
Next up is dealing with the
click events on the button and menu. If the goal is to update our state from inside our
MenuContainer component, we need to place our event handler inside
MenuContainer as well. Go ahead and add the following highlighted lines:
handleMouseDown method is called, we call
toggleMenu, which toggles whether the menu appears. At this point, you’re probably wondering where the actual code for dealing with a
click event is. What exactly will trigger a call to
handleMouseDown? The answer is, nothing so far! We’ve done things in a bit of a reverse order and defined our event handler first. We handle the association between our event handler and our
click event in a few moments when dealing with our button and menu components.
src folder, create two files called
MenuButton.css. Then open
MenuButton.js in your code editor. Inside it, add the following lines of code:
Take a moment to see what this code is doing. There isn’t a whole lot going on. We define a button element called
roundButton, and we associate the
onMouseDown event with a prop we are referencing as
handleMouseDown. Before moving on, open
MenuButton.css and add the following style rules:
Now it’s is time to actually instantiate our newly created
MenuButton component. Go back to the
MenuContainer component and add the following highlighted line inside the
For this line to actually do something, be sure to add the appropriate
import statement at the top for our
MenuButton.js file. That’s an easy one to overlook!
Notice that we are passing in a prop called
handleMouseDown, and its value is the
handleMouseDown event handler that we defined earlier. This ensures that when you click the button inside the
MenuButton component, the
handleMouseDown method that lives in the
MenuContainer component gets called. All of this is great, but our button isn’t very useful without a menu to help slide into view. We’ll fix that next.
It’s time to create our
Menu component that will be responsible for all things dealing with the menu. Before we actually create this component, let’s pretend that it already exists and call it from our
render method inside our
MenuContainer. Add the following highlighted call to our (currently imaginary)
Menu component just below where you added the call to
MenuButton a few short moments earlier:
Add the import statement for
Menu.js as well. Getting back to the
Menu component, look at the props you’re passing in. The first prop should look familiar to you. It is
handleMouseDown and its value is our
handleMouseDown event-handling method. The second prop is called
menuVisibility. Its value is the current value of our
visible state property. Now let’s go ahead and actually create our
Menu component and see, among other things, how these props get used.
In the same
src folder we have been partying in for the past few sections, add one file called
Menu.js and another file called
Menu.js, add the following contents:
Pay attention to the JSX in the
return statement. We have a
div element called
flyoutMenu with some sample content. In our
div element, we call our
handleMouseDown event-handling method (passed in via a prop) when the
onMouseDown event is overheard. Next, we set a
class value on this element; the value is the result of evaluating a variable called
visibility. As you might recall,
Getting back to our code, the value of
visibility is set a few lines earlier:
The value is either
show, depending on whether the
menuVisibility prop (whose value is specified by our
visible state property) is
false. While it might not look like it, the code revolving around
className plays a really important role in determining whether your menu is actually visible. When we look at our CSS, you’ll see why. Now open
Menu.css and add the following style rules into it:
The CSS you see here mostly deals with how our menu itself looks, but the actual showing and hiding of the menu is handled by the
#flyoutMenu.show style rules. Which of these style rules becomes active depends entirely on the code we looked at earlier. In our
div element, remember that the
class value on the generated HTML (which our CSS maps to) will be either
show, depending on what value we set for
className. Pretty cool, right?
At this point, we’re fully done with all our coding. Be sure to save all your changes and ensure that the app works just like the example we started with. Don’t nuke this project, though. We’ll be revisiting this and addressing some major shortcomings in a little bit.
This is one of the first examples we’ve looked at in which we’re using React to create a common UI occurrence, a sliding menu. As part of this, you learned more about the interplay between components, such as dealing with events/event handlers, sharing state, and so on. As we look at more examples together, you’ll see that there isn’t a whole lot more to React than what you’ve seen here. All that remains is a clever arrangement and rearrangement of the same concepts in more complex scenarios. This doesn’t mean we’re done, though. There’s more React to be had and more examples to create and fully understand!
Note: If you run into any issues, ask!
If you have any questions or your code isn’t running like you expect, don’t hesitate to ask! Post on the forums at https://forum.kirupa.com and get help from some of the friendliest and most knowledgeable people the Internet has ever brought together!