DEV Community

Cover image for Responsive Navbar in React
Gustavo Scarpim
Gustavo Scarpim

Posted on • Edited on

28 11 1 1 1

Responsive Navbar in React

Heeeeeey guys!

My name is Gustavo Scarpim, and I will show you how to make a SIMPLE and RESPONSIVE Navbar.

Creating Navbar

First we will create a file called Burger and import a component called RightNav that we will create right after, inside this file we will put the following code:

import React, { useState } from 'react';
import * as S from './styles';

import RightNav from './RightNav';

const Burger = () => {
  const [open, setOpen] = useState(false)

  return (
    <>
      <S.StyledBurger open={open} onClick={() => setOpen(!open)}>
        <div />
        <div />
        <div />
      </S.StyledBurger>
      <RightNav open={open} />
    </>
  )
}
export default Burger
Enter fullscreen mode Exit fullscreen mode

Then we will create a file called Navbar by importing your logo into a folder of your choice, or you can simply remove it, and we will also import our Burger component that was created just above.

import React from 'react';
import * as S from './styles';

import Logo from '../../assets/logo.png';
import Burger from './Burger';

type Props = {
  children?: any;
}

export default function Navbar(props: Props) {
  return (
    <>
      <S.Nav>
        <S.Logo src={Logo} alt="Etio Soluções" />
      </S.Nav>
      <Burger />
      {props.children}
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

We will create our file called RightNav by importing react-router-dom and calling your images into the assets folder.

import React from 'react'
import * as S from './styles';

import Logo from '../../assets/logo.png';
import IconReact from '../../assets/react.svg';
import IconMegamen from '../../assets/megamen.png';
import IconMario from '../../assets/mario.png';
import IconTurtle from '../../assets/turtle.png';

import { BrowserRouter as Router, Switch, Route, NavLink, Redirect } from "react-router-dom";

type Props = {
  open: boolean;
}

function RightNav(props: Props) {

  return (
    <Router>
      <S.Ul open={props.open}>
        <S.LogoUl src={Logo} alt={'Gustavo Scarpim'} />

        <NavLink to="/menu1"
          activeStyle={{
            fontWeight: "bold",
            color: "#0DADEA"
          }}
        >
          <li>Menu 1</li>
        </NavLink>
        <NavLink to="/menu2"
          activeStyle={{
            fontWeight: "bold",
            color: "#0DADEA"
          }}
        >
          <li>Menu 2</li>
        </NavLink>
        <NavLink to="/menu3"
          activeStyle={{
            fontWeight: "bold",
            color: "#0DADEA"
          }}
        >
          <li>Menu 3</li>
        </NavLink>
        <NavLink to="/menu4"
          activeStyle={{
            fontWeight: "bold",
            color: "#0DADEA"
          }}
        >
          <li>Menu 4</li>
        </NavLink>
      </S.Ul>


      <Switch>
        <Route exact path="/menu1">
          <S.Icon>
            <img src={IconReact} alt="React" />
          </S.Icon>
        </Route>
        <Route exact path="/menu2" >
          <S.Icon>
            <img src={IconMegamen} alt="Megamen" />
          </S.Icon>
        </Route>
        <Route exact path="/menu3" >
          <S.Icon>
            <img src={IconMario} alt="Mario" />
          </S.Icon>
        </Route>
        <Route exact path="/menu4" >
          <S.Icon>
            <img src={IconTurtle} alt="Turtle" />
          </S.Icon>
        </Route>

        <Redirect to='/menu1' />
      </Switch>
    </Router >
  )
}

export default RightNav
Enter fullscreen mode Exit fullscreen mode

Finally, we will create the css with styled-components, just add the following code inside a file called styles.ts

import styled from 'styled-components';

interface INav {
  open: boolean;
  href?: string;
}

export const StyledBurger = styled.div<INav>`
  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: ${(props) => props.open ? '#000' : '#000'};
    border-radius: 10px;
    transform-origin: 1px;
    transition: all 0.3s linear;
    cursor: pointer;
    &:nth-child(1) {
      transform: ${(props) => props.open ? 'rotate(45deg)' : 'rotate(0)'};
    }
    &:nth-child(2) {
      transform: ${(props) => props.open ? 'translateX(100%)' : 'translateX(0)'};
      opacity: ${(props) => props.open ? 0 : 1};
    }
    &:nth-child(3) {
      transform: ${(props) => props.open ? 'rotate(-45deg)' : 'rotate(0)'};
    }
  }
`

export const Nav = styled.nav`
  height: 100%;
  display: flex;
  justify-content: space-between;
  background-color: #fdfdfdfa;
  align-items: center;
  position: relative;

  @media (max-width: 678px) {
    width: 100vw;
  }

  span {
    font-size: 30px;
    @media only screen and (max-width: 600px) {
      font-size: 20px;
      :nth-child(2) {
        font-size: 16px !important;
        margin-top: 0px !important;
      }
    }
  }

`

export const Ul = styled.ul<INav>`
  list-style: none;
  display: flex;
  flex-flow: row nowrap;
  position: absolute;
  width: 90%;
  top: 0;
  justify-content: flex-end;
  margin-top: 0px;
  align-items: center;
  font-size: 18px;
  height: 110px;
  margin-left: 20px;

  a {
    text-decoration: none;
    text-transform: none;
    color: #000;
    cursor: pointer;

    &:hover {
      color: #0DADEA;
    }
  }

  li {
    padding: 18px 10px;
  }

  @media (max-width: 768px) {
    flex-flow: column nowrap;
    background-color: #fdfdfdfa;
    position: fixed;
    transform: ${(props) => props.open ? 'translateX(0)' : 'translateX(100%)'};
    top: -16px;
    right: 0;
    height: 100%;
    width: 180px;
    padding-top: 3.5rem;
    transition: transform 0.3s ease-in-out;
    z-index: 9;
    justify-content: normal;

    li {
      color: #000;
      margin-right: 34px;

      &:hover {
        color: #0DADEA;
      }
    }
  }
`

export const Logo = styled.img`
  margin: 20px 50px 20px 7%;
  width: 160px;
  height: 70px;
  object-fit: contain;

  @media (max-width: 1250px) {
    margin: 20px 50px 20px 5%;
  }

`

export const LogoUl = styled.img`
  margin: 20px 50px 20px 5%;
  display: none;

  @media (max-width: 768px) {
    display: flex;
    width: 160px;
    height: 70px;
    object-fit: contain;
  }
`
export const Icon = styled.div`
  width: 100vw;
  height: calc(100vh - 112px);
  display: flex;
  justify-content: center;
  align-items: center;

  img {
    width: 150px;
    height: 150px;
    pointer-events: none;
    object-fit: contain;

    @media (prefers-reduced-motion: no-preference) {
      animation: App-logo-spin infinite 20s linear;
    }
  }

    @keyframes App-logo-spin {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
  }
`
Enter fullscreen mode Exit fullscreen mode

Finally, we arrive at our main Index our Navbar component to be used in our entire project.

import React from 'react';
import ReactDOM from 'react-dom';
import reportWebVitals from './reportWebVitals';
import Menu from './components/menu/Navbar';

ReactDOM.render(
  <React.StrictMode>

    <Menu />
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();
Enter fullscreen mode Exit fullscreen mode

And ready, your menu navBar is done

Alt Text

It would look like this one (Changing the images):

Vídeo

See the complete code here on GitHub
Check out the Project in action

Thanks for reading.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more