DEV Community

Cover image for How to build a Responsive 📱 React Navigation Menu with Styled-Components 💻
Chris Hansen
Chris Hansen

Posted on • Updated on

How to build a Responsive 📱 React Navigation Menu with Styled-Components 💻

Building a React Menu does't have to be daunting. And let's use style-components while we're at it! 🔥

This may not be the most advanced React Nav, or showcase best practices, but it will get you up and running in no time!

Let's just get right into it D:

Check Out The Demo!

The Repo

Things I'll assume you have some knowledge of

  1. Dev Environment. Ex. Node, VSCode..etc.
  2. Know how to install NPM packages
  3. Have some knowledge of React
  4. Have some knowledge of React Router
  5. Some basic CSS or SCSS

1. Starting with Create-react-app

Start with a clean project. Remove the create-react-app pre-loaded files and don't forget to remove the lines of code related to testing in index.js. I also remove everything in App.js other than App.css. Remove everything inside of App.css leaving only the .App css selector with min-height: 100vh , background-color: #282c34, and position: relative

Your project should look like this
Clean react app project

And App.css should look like so
A clean css file

2. A Clean directory

  1. Create a components folder and a pages folder.

  2. Inside the components folder include 2 files: Menu.js and Toggle.js.

  3. Inside the pages folder include 3 files: HomePage.js , ExamplePage.js , ContactPage.js.

A clean directory for our react app

3. Turn files into functional components

Your HomePage.js , ExamplePage.js , and ContactPage.js should now look like this.

Example of barebones homepage component
Example of barebones examplepage component
Example of barebones contactpage component

4. Install styled-components

I prefer using Yarn package manager, so to install styled-components run this command: yarn add styled-components. If you are using NPM use this command: npm install --save styled-components. Make sure to import styled-components in each of our three pages like so: import styled from styled-components.

5. Adding styled-components our pages

The HomePage, ExamplePage and ContactPage should all share the same layout and styled-components. So just copy and paste. Don't forget to change the appropriate page name in Heading component.

They should like this
Showcasing the styled components for homepage
Showcasing the styled components for example page
Showcasing the styled components for contact page

6. Install react-router-dom

  1. Install react-router-dom into our project. yarn add react-router-dom. Or npm install --save react-router-dom.
  2. Import react router like so: import { BrowserRouter as Router, Route, Switch } from react-router-dom.
  3. Import our pages files into App.js so we can make use of React Router. Import the pages like so: import HomePage from ./pages/HomePage; import ExamplePage from ./pages/ExamplePage; import ContactPage from ./pages/ContactPage;
  4. Refer to the photo below on how to use React Router in App()

So far App.js should look like this
An example of how appjs should be looking so far

If everything has gone smoothly so far, react router should be working. In the URL, try changing the path to localhost:3000/example or to /contact

7. Complete Menu and Toggle components

  1. In step 2 we created a Menu.js and Toggle.js files in the components folder. Let's turn those into functional components.
  2. Starting with Menu.js let' import Link from react-router-dom like so: import { Link } from 'react-router-dom'). We're also going to make use of some Icons. I prefer because of simplicity. So let's install react-icons like so: yarn add react-icons Also, be sure to import the icons like so: import { FaBars, FaTimes} from 'react-icons/fa'. Don't forget to add /fa as we are importing from the Font Awesome library. Feel free to use any library, just browse the website mentioned above. If you were to use an Icon from the Material library, you would import the file like so: import { MdBars} from 'react-icons/md'. Files should like like this
    How to import reacticons from library
    How to import reacticons from library

  3. Starting with Menu.js lets once again import styled components like so: import styled from styled-components.
    You'll notice I passed Link directly into StyledLink rather than having to create an <a>anchor/</a> tag in the DOM. All we need to do is add the to attribute to our StyledLink.

  4. Then let's create our styled components for Menu.js. Starting with the StyledMenu component. It should like like this How Menujs styled component should look

  5. Followed by our StyledMenu we need links for our Menu so users can click to navigate pages. Should look like this How styled links component should look

  6. Now we need a way to switch toggle states. If the Menu is toggled or it's state is set to true, we need a way to close the Menu by toggling the state to false. Let's add a simple toggle button to our Menu. It should look like this An example of how our appjs state should look

  7. Last thing for our Menu is to add our styled-components to our Menu() like so. Don't forget to add the to='*' attribute to your links. These are required for our Router in App.js to understand which views should be rendered once a user clicks the corresponding link. For ex. if your user was to click on the /contact link, the Contact component in App.js would be rendered as we declared it's path to look like this path='/contact'.
    How the menu should look after adding our Link components

  8. Lastly we have Toggle.js. The Toggle component is the most basic. It's only responsible for changing our toggle state for our Menu. We have already turned it into a functional component, so let's first begin with importing styled-components and react-icons like so import styled from 'styled-components' and import { FaBars } from 'react-icons/fa'. Lastly, let's create the StyledToggle component, add it to our empty Toggle() component then add our FaBars icon like so
    How to create the styled toggle button component

8. Let's make use of our newly made components

  1. Back in App.js, just like we imported our pages components, let's import our Menu.js and Toggle.js components like so
    How appjs should look after importing our components

  2. Now let's add our components to our App() like so
    How appjs should look after including our components

  3. You should notice our Menu is being rendered. It's already working. You should also notice our CloseToggle button in the top right corner of our Menu. However, what you won't see is our Toggle button, because the Menu is blocking it. Let's fix this by adding state to our App with the useState() hook. At the top of your app, import the hook like so: import { useState } from 'react'. Now for our state, we need to be able to the hold the value of our toggled state, and be able to switch toggle states. It should look like this
    how to import and use the usestate hook in appjs
    We initially have our navToggled state set to false, because when a user lands on our website, the Menu should not be rendered. So logically, it makes to most sense to have the state initially set to false.

  4. To further make use of our useState hook, let's create a function for toggling our state. Let's call it setNavToggle. This functions only responsibility is to toggle the opposite state of whatever our current navToggled state is. For instance, if our current navToggled state is set to false, when the function is called, it'll set the new state to the opposite of false, making it true. If the navToggled state was true, the function will change the state to the of that value, making it true. It should look like this
    Showcasing how the handler function should look

  5. Now that we have a way to handle our Menus toggle state, let's make use of it by adding it to our Menu component. That way we can toggle our Menu to false. To do so, we are going to pass handleNavToggle to our Menu component as a prop. Like so
    Showcasing how to add our handler as a prop to our component

  6. Now that we have passed our handler function to our Menu component as a prop, we now have the ability to change our state from within the Menu component. But first let's accept the passed in prop from within our Menu component first. Like so
    How to accept and destructure the prop in our menu component

  7. Now our intention is to be able to close the Menu, or toggle the Menus state to false. Let's do that by adding a click event listener our CloseToggle component, then pass in our handleNavToggle. In React, you need to use camelCase, so it should like so onClick={handleNavToggle}
    Adding the prop to our toggle button

  8. You'll notice if you click the CloseToggle button, nothing is happening. That's because back in App.js we are forcing the render of our Menu component, no matter the state. Let's fix that by dynamically rendering our Menu component by using a ternary operator. It should look like this
    How to use a ternary operator to render our menu in appjs
    I'll explain in pseudocode. Here we are saying, if the navToggle state is true ? render <Menu/> : if its not, then return null. We're looking to see if the value of what's on the left of the ? is true. In this case, we're looking to see if the NavToggled state is true. If the navToggle state is indeed true, we're then going to render whatever is on the right side of the ?. And if it is not true, just like an if else statement, we're going to render whatever is on the right side of the :. In this case, we want to render nothing. So we use null. Essentially, it's if ? do this : else do this.
    You should also notice that if you try to toggle the CloseToggle button, that it works. Because we are only rendering the Menu if the state is true. You'll also notice if we attempt to toggle the Menu again, nothing happens.

  9. Let's add functionality to our Toggle component! Back in App.js, we just pass in our handler function as a prop to our Toggle component like so
    Showcasing how to add functionality to our toggle component

  10. Back in Toggle.js lets again accept our passed in handler function by restructuring it like so
    How to accept the passed in prop to togglejs

  11. Now add our function as a click event to the StyledToggle like so
    how to add the click event handler for our toggle component

If everything has gone smoothly so far, it should be fully
functional, and fully responsive!

9. 👏 Congrats! 🔥

You have successfully built a fully responsive React navigation with Styled-components! If it's not exactly turning out as planned, I am more than happy to help you find the solution! Either use the comments section below, or DM me on Twitter!

10. Bonus animations!

Let's make our React app even better with some swanky animations.

  1. We're going to use animate.css. It's a lightweight animation library, and it's very easy to implement into react apps. Install like so yarn add animate.css, or npm install --save animate.css

  2. Inside of index.js below import App from './App'; add import 'animate.css';

  3. And just like that our entire app has access to animate.css.

  4. Let's first add some animations to our Link components and our single CloseToggle component in Menu.js. Like so className="animate__animated animate__fadeInRight"
    How the link component should look with our animation classes
    Just like that, we should have some slick animations in our Menu. Be careful to not get carried away with animations. It's not recommended to add animations to the entire parent div. For example, you should not add these sort of animations to the entire StyledMenu component as it can cause some performance issues!

  5. Lastly, back in HomePage.js, ExamplePage.js and ContactPage.js, let's do something similar. Let's add some animations to our Heading component. Like this className="animate__animated animate__fadeInLeft". Heres an example of HomePage.js
    An example of how homepage should look with animations

Conclusion! 👋

That's a wrap on How to build a Responsive 📱 React Navigation Menu with Styled-Components 💻. If you made it this far, you have a lot of time on your hands. Lol 🤣 Thank you so much for your time, and I hope it was successful!

Please don't hesitate to hit me up on Twitter in regards to any questions, concerns or if you just wanna talk code!

Happy coding! ✌️

Are you a beginner web developer!?

Top comments (7)

link2twenty profile image
Andrew Bone

Hi, I've just had a quick look at your demo and it looks like your menu is not accessible without a mouse. This would be a quick fix you can use styled buttons rather than the icons directly as the buttons come with keyboard support out the box.

hyggedev profile image
Chris Hansen

Hey there, thanks for letting me know. You mean it's not accessible with a keyboard? Because it works with mobile D: Unless that's obvious, but you're strictly speaking about keyboard accessible! I'll check it out 👍

link2twenty profile image
Andrew Bone

Yes sorry i mean not accessible without pointer input (so mouse or touch)

Thread Thread
hyggedev profile image
Chris Hansen

Hey no worries! I just fixed the issue. I left the default button styles too, because I think it looks bad ass! Haha. Works with the theme.
Also, thanks for sharing your thoughts. I see your'e into accessibility, and I think we all should be. I'd like to spend more time concentrating on accessibility while coding. I appreciate it✌️

rualan profile image

Hi. I have done the same thing but I can't understand where I am making the mistake. The browser just displays the background only. Here is my app.css which i don't think the problem is coming from. However, the home page (and any other page) is not displayed at all
.App {
min-height: 100vh;
background-color: black;
position: relative;

hyggedev profile image
Chris Hansen

Hey, that suck! Well let's figure it out.

First, are you using dev tools? Like chrome dev tools on the chrome browser? Firefox works well too.

Secondly, are you sure you have React router set up correctly? React-router just had an update, so you should be made aware. It's now React Router v6. I believe it's breaking changes if you don't have a production app yet. Minor changes tho, look at the docs, they show the old vs new way.

Thirdly, your body text made relative to your #000 background color?

Let's start here.

rualan profile image

Thanks so much for your feedback. Yes I am using Chrome Dev Tools. The body text is different from the background colour. I realised that my React-Router wasn't set up correctly as you have stated, I did an update and it worked. Thanks for the assistance.