Search code examples
css

Why is the menu overlapping the hamburger icon?


I created a simple hamburger menu. The base layout of the website needs to use grid. The menu works fine, but when you reduce the browser window size and the hamburger icon appears, clicking on it causes the menu to overlap the bottom half of the hamburger icon.

"use strict";

// Hamburger navigation
const menuToggle = document.querySelector(".menu-toggle");
const nav = menuToggle.parentElement;

menuToggle.addEventListener("click", event => {
  event.preventDefault();
  nav.classList.toggle("open");
});
:root {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
}

.grid-container {
  display: grid;
  grid-gap: 10px;
  grid-template-areas:
    "header"
    "nav"
}

header {
  grid-area: header;
}

.nav {
  grid-area: nav;
  position: relative;
}

/* Hamburger icon */
.menu-toggle {
  position: absolute;
  right: 0;
  top: 50%;
  width: 80px;
  height: 80px;
  cursor: pointer;
  transform: translateY(-50%);
}

.hamburger {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.hamburger,
.hamburger::before,
.hamburger::after {
  position: absolute;
  content: "";
  height: 3px;
  width: 30px;
  background: #0c0c0c;
  border-radius: 0.5626em;
  transition: all .4s ease-in-out;
}

.hamburger::before {
  top: -8px;
}

.hamburger::after {
  top: 8px;
}

/* Hamburger animation */
.nav.open .hamburger {
  background: rgba(0, 0, 0, 0);
}

.nav.open .hamburger::before {
  top: 0;
  transform: rotate(45deg);
}

.nav.open .hamburger::after {
  top: 0;
  transform: rotate(135deg);
}

/* Dropdown */
.menu-dropdown {
  position: absolute;
  max-height: 0;
  top: 100%;
  width: 100%;
  background: #fff;
  overflow: hidden;
  transition: max-height 0.6s ease-in-out;
}

.nav-menu {
  white-space: nowrap;
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav-menu > li + li {
  margin-top: 0;
  border-top: 1px solid #ccc;
}

.nav-menu > li > a {
  display: block;
  font-size: 1.3rem;
  padding: .8em .5em;
  text-decoration: none;
  text-transform: uppercase;
}

.nav.open .menu-dropdown {
  max-height: 100vh;
}

@media (min-width: 52em) {
  .grid-container {
    grid-template-columns: minmax(300px, 800px);
    justify-content: center;
  }

  .tags {
    grid-template-columns: repeat(3, 1fr);
  }

  .menu-toggle {
    display: none;
  }

  .menu-dropdown {
    position: initial;
    overflow: initial;
    max-height: initial;
  }

  .nav-menu {
    display: flex;
    justify-content: center;
  }

  .nav-menu > li + li {
    margin-left: 2.3em;
    border-top: initial;
  }

}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <script src="script.js" defer></script>
  <title>Menu</title>
</head>
<body>
  <div class="grid-container">
    <header>
      Header
    </header>
    <nav class="nav">
      <div class="menu-toggle">
        <div class="hamburger"></div>
      </div>

      <div class="menu-dropdown">
        <ul class="nav-menu">
          <li><a href="#">Home</a></li>
          <li><a href="#">About Us</a></li>
          <li><a href="#">Services</a></li>
          <li><a href="#">Prices</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
      </div> <!-- / .menu-dropdown -->
    </nav> <!-- / .nav -->

  </div>
</body>
</html>

Any idea what might be causing the menu to cover half of the hamburger icon? I spent over half an hour trying different options, but I couldn't figure it out. The menu should open right below the hamburger icon.

Here's another version which works:

"use strict";

// Hamburger navigation
const menuToggle = document.querySelector(".menu-toggle");
const nav = menuToggle.parentElement;

menuToggle.addEventListener("click", event => {
  event.preventDefault();
  nav.classList.toggle("open");
});
:root {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
  font-family: Arial, sans-serif;
}

.header {
  height: 100px;
  background: #fff;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
}

.header-container {
  position: relative;
  height: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.logo {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Hamburger icon */
.menu-toggle {
  position: absolute;
  right: 0;
  top: 50%;
  width: 80px;
  height: 80px;
  cursor: pointer;
  transform: translateY(-50%);
}

.hamburger {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.hamburger,
.hamburger::before,
.hamburger::after {
  position: absolute;
  content: "";
  height: 3px;
  width: 30px;
  background: #0c0c0c;
  border-radius: 0.5626em;
  transition: all .4s ease-in-out;
}

.hamburger::before {
  top: -8px;
}

.hamburger::after {
  top: 8px;
}

/* Hamburger animation */
.nav.open .hamburger {
  background: rgba(0, 0, 0, 0);
}

.nav.open .hamburger::before {
  top: 0;
  transform: rotate(45deg);
}

.nav.open .hamburger::after {
  top: 0;
  transform: rotate(135deg);
}

/* Dropdown */
.menu-dropdown {
  position: absolute;
  max-height: 0;
  top: 100%;
  width: 100%;
  background: #fff;
  overflow: hidden;
  transition: max-height 0.6s ease-in-out;
}

.nav-menu {
  white-space: nowrap;
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav-menu > li + li {
  margin-top: 0;
  border-top: 1px solid #ccc;
}

.nav-menu > li > a {
  display: block;
  font-size: 1.3rem;
  padding: .8em .5em;
  text-decoration: none;
  text-transform: uppercase;
}

.nav.open .menu-dropdown {
  max-height: 100vh;
}

@media (min-width: 52em) {
  .menu-toggle {
    display: none;
  }

  .header-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .logo {
    position: initial;
    transform: initial;
  }

  .menu-dropdown {
    position: initial;
    overflow: initial;
    max-height: initial;
  }

  .nav-menu {
    display: flex;
    justify-content: center;
  }

  .nav-menu > li + li {
    margin-left: 2.3em;
    border-top: initial;
  }
}
<!DOCTYPE html>
<html lang="en-US">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="nav-simple.css">
  <title>Hamburger Navigation</title>
</head>
<body>
  <header class="header">
    <div class="header-container">

      <!-- Site logo -->
      <div class="logo">
        <a href="#">
          <img src="logo.png" alt="logo">
        </a>
      </div>

      <!-- Site navigation -->
      <nav class="nav">
        <div class="menu-toggle">
          <div class="hamburger"></div>
        </div>

        <div class="menu-dropdown">
          <ul class="nav-menu">
            <li><a href="#">Home</a></li>
            <li><a href="#">About Us</a></li>
            <li><a href="#">Services</a></li>
            <li><a href="#">Prices</a></li>
            <li><a href="#">Contact</a></li>
          </ul>
        </div> <!-- / .menu-dropdown -->
      </nav> <!-- / .nav -->
    </div> <!-- / .header-container -->
  </header>

  <script src="nav-simple.js"></script>
</body>
</html>

Considering that this second version works, does it may have to do with grid in the first code?


Solution

  • Without changing your current layout, it can be fixed by adding the z-index property on the .menu-toggle.

    .menu-toggle {
        z-index: 50;
    }
    
    Old JSFiddle Demo

    Update

    "use strict";
    
    // Hamburger navigation
    const menuToggle = document.querySelector(".menu-toggle");
    const nav = menuToggle.parentElement;
    
    menuToggle.addEventListener("click", event => {
      event.preventDefault();
      nav.classList.toggle("open");
    });
    :root {
      box-sizing: border-box;
    }
    
    *,
    *::before,
    *::after {
      box-sizing: inherit;
    }
    
    body {
      margin: 0;
      padding: 0;
    }
    
    .grid-container {
      display: grid;
      grid-gap: 10px;
      grid-template-areas:
        "header"
        "nav";
    }
    
    header {
      grid-area: header;
    }
    
    .nav {
      grid-area: nav;
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: flex-end;
    }
    
    .menu-toggle {
      width: 50px;
      height: 50px;
      cursor: pointer;
      position: relative;
      z-index: 100; 
    }
    
    .hamburger,
    .hamburger::before,
    .hamburger::after {
      position: absolute;
      content: "";
      height: 3px;
      width: 30px;
      background: #0c0c0c;
      border-radius: 0.5626em;
      transition: all 0.4s ease-in-out;
    }
    
    .hamburger {
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    .hamburger::before {
      top: -8px;
    }
    
    .hamburger::after {
      top: 8px;
    }
    
    .nav.open .hamburger {
      background: rgba(0, 0, 0, 0);
    }
    
    .nav.open .hamburger::before {
      top: 0;
      transform: rotate(45deg);
    }
    
    .nav.open .hamburger::after {
      top: 0;
      transform: rotate(135deg);
    }
    
    .menu-dropdown {
      position: absolute;
      top: 100%; 
      right: 0;
      width: 100%;
      background: #fff;
      overflow: hidden;
      max-height: 0;
      transition: max-height 0.6s ease-in-out;
    }
    
    .nav-menu {
      white-space: nowrap;
      list-style: none;
      padding: 0;
      margin: 0;
    }
    
    .nav-menu > li + li {
      margin-top: 0;
      border-top: 1px solid #ccc;
    }
    
    .nav-menu > li > a {
      display: block;
      font-size: 1.3rem;
      padding: 0.8em 0.5em;
      text-decoration: none;
      text-transform: uppercase;
    }
    
    .nav.open .menu-dropdown {
      max-height: 300px;
    }
    
    @media (min-width: 52em) {
      .grid-container {
        grid-template-columns: minmax(300px, 800px);
        justify-content: center;
      }
    
      .tags {
        grid-template-columns: repeat(3, 1fr);
      }
    
      .menu-toggle {
        display: none;
      }
    
      .menu-dropdown {
        position: initial;
        overflow: initial;
        max-height: initial;
      }
    
      .nav-menu {
        display: flex;
        justify-content: center;
      }
    
      .nav-menu > li + li {
        margin-left: 2.3em;
        border-top: initial;
      }
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="style.css">
      <script src="script.js" defer></script>
      <title>Menu</title>
    </head>
    <body>
      <div class="grid-container">
        <header>
          Header
        </header>
        <nav class="nav">
          <div class="menu-toggle">
            <div class="hamburger"></div>
          </div>
    
          <div class="menu-dropdown">
            <ul class="nav-menu">
              <li><a href="#">Home</a></li>
              <li><a href="#">About Us</a></li>
              <li><a href="#">Services</a></li>
              <li><a href="#">Prices</a></li>
              <li><a href="#">Contact</a></li>
            </ul>
          </div> <!-- / .menu-dropdown -->
        </nav> <!-- / .nav -->
      </div>
    </body>
    </html>