DEV Community

Linh Truong Cong Hong
Linh Truong Cong Hong

Posted on

Responsive navigation menu with plain JavaScript

Source code of this blog post could be found at:
https://github.com/linhtch90/devto-responsive-nav-plain-js.git
Showcase:
https://linhtch90.github.io/devto-responsive-nav-plain-js/

Introduction

Making a responsive navigation menu is a common task of frontend developers. The purpose of this blog post is to introduce necessary steps to build up a navigation menu which disappears at small screen (less than 600px) and get replaced by a hamburger button.

Main functions include:

  1. When you press the hamburger button: A side menu show up and the hamburger button is replace by a close button.

  2. When you press the close button or any menu item: The side bar collapses and the hamburger button show up again.

Step 1

Let's make a simple webpage with html for demonstration purpose as below and save it as ./index.html

Please make sure that you also create folders for css and javascript files with similar names and paths as mentioned in the html file which is ./css/style.css and ./js/hamburger.js, respectively.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- Styling -->
    <link rel="stylesheet" href="./css/style.css" />
    <!-- Google font: Open sans -->
    <link
      href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700;800&display=swap"
      rel="stylesheet"
    />
    <!-- Fontawesome -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
    />

    <title>
      Responsive navigation menu example
    </title>
  </head>
  <body>
    <div id="ham-button" class="hamburger-button" onclick="hamburgerMenu()">
      <i id="ham-icon" class="fas fa-bars"></i>
    </div>

    <div id="ham-menu" class="hamburger-menu">
      <ul>
        <li>
          <a href="#navigation"><div onclick="hamburgerMenu()">Home</div></a>
        </li>
        <li>
          <a href="#about"><div onclick="hamburgerMenu()">About</div></a>
        </li>
        <li>
          <a href="#projects"><div onclick="hamburgerMenu()">Projects</div></a>
        </li>
        <li>
          <a href="#blog"><div onclick="hamburgerMenu()">Blogs</div></a>
        </li>
        <li>
          <a href="#footer"><div onclick="hamburgerMenu()">Contact</div></a>
        </li>
      </ul>
    </div>
    <!-- Navigation bar -->
    <section id="navigation">
      <div class="container-dark">
        <nav class="navigation-bar">
          <ul>
            <li><a href="#navigation">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#projects">Projects</a></li>
            <li><a href="#blog">Blogs</a></li>
            <li><a href="#footer">Contact</a></li>
          </ul>
        </nav>
      </div>
    </section>
    <!-- Home -->
    <section id="home">
      <div class="container-dark">
        <div class="container-home">Home</div>
      </div>
    </section>
    <!-- About -->
    <section id="about">
      <div class="container-light">
        <div class="container-about">About</div>
      </div>
    </section>

    <!-- Projects -->
    <section id="projects">
      <div class="container-dark">
        <div class="container-projects">Projects</div>
      </div>
    </section>

    <!-- Skills -->
    <section id="skills">
      <div class="container-light">
        <div class="container-skills">Skills</div>
      </div>
    </section>

    <!-- Timeline -->
    <section id="timeline">
      <div class="container-dark">
        <div class="container-timeline">Timeline</div>
      </div>
    </section>

    <!-- Blog -->
    <section id="blog">
      <div class="container-light">
        <div class="container-blog">Blog</div>
      </div>
    </section>

    <!-- Footer -->
    <section id="footer">
      <footer>
        <div class="container-dark">
          <div class="container-footer">
            <div class="footer-icon-list">
              <i class="fab fa-twitter footer-icon"></i>
              <i class="fab fa-linkedin footer-icon"></i>
              <i class="fab fa-github footer-icon"></i>
              <i class="fab fa-dev footer-icon"></i>
              <i class="fab fa-instagram footer-icon"></i>
            </div>
          </div>
        </div>
      </footer>
    </section>

    <script type="text/javascript" src="./js/hamburger.js"></script>
  </body>
</html>

Step 2

Let's make our html look better and responsible by adding some CSS to ./css/style.css

html {
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body {
  font-family: "Open Sans", sans-serif;
  margin: 0px;
  background-color: rgb(51, 44, 56);
  box-sizing: border-box;
  overflow-x: hidden;
}

h1 {
  padding: 0;
  margin: 0;
}

h2 {
  margin: 0;
  padding: 0;
}

p {
  margin: 0;
  padding: 0;
}

.container-dark {
  display: flex;
  width: 100%;
  justify-content: center;
}

.container-light {
  display: flex;
  width: 100%;
  justify-content: center;
  background-color: whitesmoke;
}

/* Hamburger button */

.hamburger-button {
  display: none;
}

.hamburger-menu {
  display: none;
}

/* Navigation bar */

.navigation-bar {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 75%;
  height: 10vh;
}

.navigation-bar > ul {
  display: flex;
  width: 100%;
  list-style-type: none;
  justify-content: space-between;
  flex-direction: row;
  padding: 0;
}

.navigation-bar > ul > li {
  width: fit-content;
}

.navigation-bar > ul > li > a {
  text-decoration: none;
  color: whitesmoke;
  font-weight: 700;
  letter-spacing: 0.2rem;
}

.navigation-bar > ul > li > a:hover {
  color: green;
  transition: 0.75s;
  cursor: pointer;
}

/* Home section */

.container-home {
  display: flex;
  width: 75%;
  height: 90vh;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* About section */

.container-about {
  display: flex;
  width: 75%;
  height: 20rem;
  background-color: whitesmoke;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* Projects */

.container-projects {
  display: flex;
  width: 75%;
  height: 20rem;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* Skills */

.container-skills {
  display: flex;
  width: 75%;
  height: 20rem;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* Timeline */

.container-timeline {
  display: flex;
  width: 75%;
  height: 20rem;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* Blog */

.container-blog {
  display: flex;
  width: 75%;
  height: 20rem;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

/* Footer */

.container-footer {
  display: flex;
  width: 75%;
  height: 20rem;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: green;
}

.footer-icon-list {
  font-size: 1.5rem;
  color: whitesmoke;
  margin-top: 2rem;
  margin-bottom: 2rem;
  letter-spacing: 1rem;
}

.footer-icon:hover {
  color: green;
  cursor: pointer;
  transition: 0.75s;
}

/* Responsive  */

/* For mobile large */

@media only screen and (max-width: 600px) {
  .navigation-bar {
    visibility: hidden;
  }

  li a.icon {
    visibility: visible;
  }

  /* Home */

  .container-home {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 20rem;
    justify-content: center;
    align-items: center;
    margin-top: 0;
    padding-top: 0;
  }

  /* About section */

  .container-about {
    display: flex;
    height: auto;
    width: 75%;
    height: 20rem;
    background-color: whitesmoke;
  }

  /* Projects */

  .container-projects {
    width: 100%;
  }

  /* Skills */

  .container-skills {
    width: 100%;
  }

  /* Timeline */

  .container-timeline {
    width: 60%;
  }

  /* Blog */

  .container-blog {
    width: 100%;
  }

  /* Footer */

  .container-footer {
    width: 100%;
  }

  /* Hamburger button */
  .hamburger-button {
    display: block;
    font-size: 2rem;
    color: green;
    background-color: transparent;
    border: none;
    position: fixed;
    left: 1rem;
    top: 1rem;
    z-index: 30;
  }

  .hamburger-menu {
    display: none;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100vh;
    padding: 0;
    position: fixed;
    left: 0;
    top: 0;
    z-index: 20;
    background-color: rgb(51, 44, 56);
  }

  .hamburger-menu > ul {
    display: flex;
    flex-direction: column;
    width: 100%;
    list-style-type: none;
    justify-content: center;
    align-items: center;
    padding: 0;
  }

  .hamburger-menu > ul > li {
    width: fit-content;
    margin: 1.5rem;
  }

  .hamburger-menu > ul > li > a {
    text-decoration: none;
    font-size: 2rem;
    color: whitesmoke;
    font-weight: 700;
    letter-spacing: 0.2rem;
  }

  .hamburger-menu > ul > li > a:hover {
    color: green;
    transition: 0.75s;
    cursor: pointer;
  }
}

Step 3

Add the below code to ./js/hamburger.js

This is the code for handling the collapsible menu bar as well as toggling the hamburger button and close button.

function hamburgerMenu() {
  // Toggle the side menu
  let hamburgerMenu = document.querySelector(".hamburger-menu");
  let menuStyle = getComputedStyle(hamburgerMenu);

  if (menuStyle.display == "none") {
    document.getElementById("ham-menu").style.display = "flex";
  } else {
    document.getElementById("ham-menu").style.display = "none";
  }

  // Exchange hamburger icon and close icon
  let hamburgerIcon = document.querySelector("#ham-icon");
  if (hamburgerIcon.classList.contains("fa-bars")) {
    hamburgerIcon.classList.replace("fa-bars", "fa-times-circle");
    return;
  } else {
    hamburgerIcon.classList.replace("fa-times-circle", "fa-bars");
    return;
  }
}

DONE!

Now you can open ./index.html file with your web browser and inspect the responsive navigation menu that we have just built.

Happy coding!

Discussion (2)

Collapse
hugekontrast profile image
Ashish Khare😎

Great code! Dope skills of your's. But it would be highly helpful to give a preview of it in the post like including codepen.
Thank you.

Collapse
linhtch90 profile image
Linh Truong Cong Hong Author

Good tip! Thank you so much for the first comment on my first blog post on Dev.to! 😃