In order to build a website with a good user experience, there are a lot of things to consider, one of which is how responsive your site will be. Your site can be responsive and still have a bad user experience. But how do you solve this? In this article, we will go through building a responsive hamburger navigation menu from scratch in Reactjs, using styled-component for styling. To do this, there are a few things to handle.
Setup Create app
In your terminal, run the following scripts. Then open http://localhost:3000
to see your app.
npx create-react-app responsive-nabar
cd responsive-nabar
npm start
- Running
npx create-react-app responsive-nabar
creates a new react application in theresponsive-navbar
directory. cd responsive-nabar
changes directory into theresponsive-nabar
directory, which is where the new react application was created.- Lastly,
npm start
gets our react server running While your app is running, install styled components using the following scripts.
npm install styled-components
Go to your root directory and clear out the create react app files we won't be needing. Your directory structure should look exactly like this
Open your index.html and add the following code directly below the
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
</style>
This sets the box-sizing property on all elements to border-box
, and ensures that no element on any of the pages has default padding and/or margin applied to it.
Update your App.js file with the following code
// App.jsx
import React from 'react';
function App() {
return (
<div className="App">
App
</div>
);
}
export default App;
Your RightNav.jsx, Burger.jsx, and Navbar.jsx files should have the respective codes below
// App.jsx
import React from 'react';
import Navbar from './Nav/Navbar';
function App() {
return (
<div className="App">
<Navbar />
App
</div>
);
}
export default App;
// RightNave.jsx
import React from 'react';
const RightNav = () => {
return (
<ul>
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
<li>Sign In</li>
<li>Sign Up</li>
</ul>
)
}
export default RightNav
// Burger.jsx
import React, { useState } from 'react';
import styled from 'styled-components';
import RightNav from './RightNav';
const Burger = () => {
const [open, setOpen] = useState(false)
return (
<React.Fragment>
<div>
<div />
<div />
<div />
</div>
<RightNav open={open}/>
</React.Fragment>
)
};
export default Burger;
// Navbar.jsx
import React from 'react';
import Burger from './Burger';
const Nav = styled.nav`
// css goes here
`;
const Navbar = () => {
return (
<Nav>
<div className="logo">
Nav Bar
</div>
<Burger />
</Nav>
)
}
export default Navbar
After this, your app should look as shown below with no styling yet.
Let's style our navigation menu.
Given that we already install styled-components, our RightNav.jsx, Burger.jsx, and Navbar.jsx components will finally look as follows.
import React, { useState } from 'react';
import styled from 'styled-components';
import RightNav from './RightNav';
const StyledBurger = styled.div`
width: 2rem;
height: 2rem;
position: fixed;
top: 15px;
right: 20px;
z-index: 20;
display: none;
@media (max-width: 768px) {
display: flex;
justify-content: space-around;
flex-flow: column nowrap;
}
div {
width: 2rem;
height: 0.25rem;
background-color: ${({ open }) => open ? '#ccc' : '#333'};
border-radius: 10px;
transform-origin: 1px;
transition: all 0.3s linear;
&:nth-child(1) {
transform: ${({ open }) => open ? 'rotate(45deg)' : 'rotate(0)'};
}
&:nth-child(2) {
transform: ${({ open }) => open ? 'translateX(100%)' : 'translateX(0)'};
opacity: ${({ open }) => open ? 0 : 1};
}
&:nth-child(3) {
transform: ${({ open }) => open ? 'rotate(-45deg)' : 'rotate(0)'};
}
}
`;
const Burger = () => {
const [open, setOpen] = useState(false)
return (
<>
<StyledBurger open={open} onClick={() => setOpen(!open)}>
<div />
<div />
<div />
</StyledBurger>
<RightNav open={open}/>
</>
)
}
export default Burger
import React from 'react';
import styled from 'styled-components';
import Burger from './Burger';
const Nav = styled.nav`
width: 100%;
height: 55px;
border-bottom: 2px solid #f1f1f1;
padding: 0 20px;
display: flex;
justify-content: space-between;
.logo {
padding: 15px 0;
}
`
const Navbar = () => {
return (
<Nav>
<div className="logo">
Nav Bar
</div>
<Burger />
</Nav>
)
}
export default Navbar
import React from 'react';
import styled from 'styled-components';
const Ul = styled.ul`
list-style: none;
display: flex;
flex-flow: row nowrap;
li {
padding: 18px 10px;
}
@media (max-width: 768px) {
flex-flow: column nowrap;
background-color: #0D2538;
position: fixed;
transform: ${({ open }) => open ? 'translateX(0)' : 'translateX(100%)'};
top: 0;
right: 0;
height: 100vh;
width: 300px;
padding-top: 3.5rem;
transition: transform 0.3s ease-in-out;
li {
color: #fff;
}
}
`;
const RightNav = ({ open }) => {
return (
<Ul open={open}>
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
<li>Sign In</li>
<li>Sign Up</li>
</Ul>
)
}
export default RightNav
import React, { useState } from 'react';
import styled from 'styled-components';
import RightNav from './RightNav';
const StyledBurger = styled.div`
width: 2rem;
height: 2rem;
position: fixed;
top: 15px;
right: 20px;
z-index: 20;
display: none;
@media (max-width: 768px) {
display: flex;
justify-content: space-around;
flex-flow: column nowrap;
}
div {
width: 2rem;
height: 0.25rem;
background-color: ${({ open }) => open ? '#ccc' : '#333'};
border-radius: 10px;
transform-origin: 1px;
transition: all 0.3s linear;
&:nth-child(1) {
transform: ${({ open }) => open ? 'rotate(45deg)' : 'rotate(0)'};
}
&:nth-child(2) {
transform: ${({ open }) => open ? 'translateX(100%)' : 'translateX(0)'};
opacity: ${({ open }) => open ? 0 : 1};
}
&:nth-child(3) {
transform: ${({ open }) => open ? 'rotate(-45deg)' : 'rotate(0)'};
}
}
`;
const Burger = () => {
const [open, setOpen] = useState(false)
return (
<>
<StyledBurger open={open} onClick={() => setOpen(!open)}>
<div />
<div />
<div />
</StyledBurger>
<RightNav open={open}/>
</>
)
}
export default Burger
import React from 'react';
import styled from 'styled-components';
import Burger from './Burger';
const Nav = styled.nav`
width: 100%;
height: 55px;
border-bottom: 2px solid #f1f1f1;
padding: 0 20px;
display: flex;
justify-content: space-between;
.logo {
padding: 15px 0;
}
`
const Navbar = () => {
return (
<Nav>
<div className="logo">
Nav Bar
</div>
<Burger />
</Nav>
)
}
export default Navbar
import React from 'react';
import styled from 'styled-components';
const Ul = styled.ul`
list-style: none;
display: flex;
flex-flow: row nowrap;
li {
padding: 18px 10px;
}
@media (max-width: 768px) {
flex-flow: column nowrap;
background-color: #0D2538;
position: fixed;
transform: ${({ open }) => open ? 'translateX(0)' : 'translateX(100%)'};
top: 0;
right: 0;
height: 100vh;
width: 300px;
padding-top: 3.5rem;
transition: transform 0.3s ease-in-out;
li {
color: #fff;
}
}
`;
const RightNav = ({ open }) => {
return (
<Ul open={open}>
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
<li>Sign In</li>
<li>Sign Up</li>
</Ul>
)
}
export default RightNav
import React, { useState } from 'react';
import styled from 'styled-components';
import RightNav from './RightNav';
const StyledBurger = styled.div`
width: 2rem;
height: 2rem;
position: fixed;
top: 15px;
right: 20px;
z-index: 20;
display: none;
@media (max-width: 768px) {
display: flex;
justify-content: space-around;
flex-flow: column nowrap;
}
div {
width: 2rem;
height: 0.25rem;
background-color: ${({ open }) => open ? '#ccc' : '#333'};
border-radius: 10px;
transform-origin: 1px;
transition: all 0.3s linear;
&:nth-child(1) {
transform: ${({ open }) => open ? 'rotate(45deg)' : 'rotate(0)'};
}
&:nth-child(2) {
transform: ${({ open }) => open ? 'translateX(100%)' : 'translateX(0)'};
opacity: ${({ open }) => open ? 0 : 1};
}
&:nth-child(3) {
transform: ${({ open }) => open ? 'rotate(-45deg)' : 'rotate(0)'};
}
}
`;
const Burger = () => {
const [open, setOpen] = useState(false)
return (
<>
<StyledBurger open={open} onClick={() => setOpen(!open)}>
<div />
<div />
<div />
</StyledBurger>
<RightNav open={open}/>
</>
)
}
export default Burger
import React from 'react';
import styled from 'styled-components';
import Burger from './Burger';
const Nav = styled.nav`
width: 100%;
height: 55px;
border-bottom: 2px solid #f1f1f1;
padding: 0 20px;
display: flex;
justify-content: space-between;
.logo {
padding: 15px 0;
}
`
const Navbar = () => {
return (
<Nav>
<div className="logo">
Nav Bar
</div>
<Burger />
</Nav>
)
}
export default Navbar
import React from 'react';
import styled from 'styled-components';
const Ul = styled.ul`
list-style: none;
display: flex;
flex-flow: row nowrap;
li {
padding: 18px 10px;
}
@media (max-width: 768px) {
flex-flow: column nowrap;
background-color: #0D2538;
position: fixed;
transform: ${({ open }) => open ? 'translateX(0)' : 'translateX(100%)'};
top: 0;
right: 0;
height: 100vh;
width: 300px;
padding-top: 3.5rem;
transition: transform 0.3s ease-in-out;
li {
color: #fff;
}
}
`;
const RightNav = ({ open }) => {
return (
<Ul open={open}>
<li>Home</li>
<li>About Us</li>
<li>Contact Us</li>
<li>Sign In</li>
<li>Sign Up</li>
</Ul>
)
}
export default RightNav
You can now check your app on the browser and it should look like this
Conclusion
Finally, you should have a responsive navigation menu with some nice hamburger animations when clicked. In case you face any problems, you can reference the repository on GitHub. Or, leave a comment in the comment section and I will reply ASAP..
Thanks