Search code examples
htmlsassresponsive-designnavbarhamburger-menu

Check box doesn't open up menu when toggled


I am making a responsive navbar which turns into the hamburger icon on mobile phones. I used media queries to check for mobile phones and create a hamburger icon. Then I made a mobile menu which appears and disappears when the hamburger icon gets toggled. Here is my code:

HTML:

<!DOCTYPE html>

<html>
  <head>
    <meta charset="UTF-8" />
    <title>Responsive Nav Bar</title>
    <link rel="stylesheet" href="style.css" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
  </head>

  <body>
    <!-- Nav Bar -->
    <nav>
      <h2>Nav Bar</h2>
      <div class="nav-left">
        <a>Home</a>
        <a>About</a>
        <a>Blog</a>
        <a>Contact</a>
      </div>
      <div class="nav-right">
        <a>Log In</a>
        <a>Sign Up</a>
      </div>

      <div class="mobile-nav">
        <label for="toggle"><h2>&#9776;</h2></label>
        <input type="checkbox" id="toggle">
      </div>
      <div class="menu"> <!-- Mobile Menu -->
        <a>Home</a>
        <a>About</a>
        <a>Blog</a>
        <a>Contact</a>
        <hr>
        <a>Log In</button>
        <a>Sign Up</button>
      </div>
    </nav>
  </body>
</html>

SASS (Use Compiler):

// Fonts
@import url("https://fonts.googleapis.com/css2?family=Mukta&display=swap");


* {
  margin: 0px;
  padding: 0px;
}

// Navbar
nav {
  width: auto;
  padding: 30px;
  background-color: #fafafa;
  display: flex;
  align-content: center;
  flex-wrap: wrap;

  h2 {
    color: #303030;
    font-family: "Mukta", sans-serif;
    margin-right: 30px;
  }
}

.nav-right {
  margin-left: auto;

  a {
    margin-right: 15px;
    margin-top: auto;
    font-family: "Mukta", sans-serif;
    text-decoration: none;
    color: rgb(109, 109, 109);
    transition: all 0.4s ease;
  }

  a:hover {
    color: #26b1db;
  }
}

.nav-left {
  display: flex;
  align-content: center;

  a {
    margin-right: 15px;
    margin-top: auto;
    font-family: "Mukta", sans-serif;
    text-decoration: none;
    color: rgb(109, 109, 109);
    transition: all 0.4s ease;
  }

  a:hover {
    color: #26b1db;
  }
}

div.mobile-nav {
  display: none;

  label {
    display: none;
  }

  #toggle {
    display: none;
  }
}

.menu {     // Mobile Menu Styling, Display is none
  width: 100vw;
  font-family: "Mukta", sans-serif;
  display: none;
  flex-direction: column;
  background-color: #fafafa;
  z-index: 1000;

  a {
    margin: 5px 0px;
    transition: all 0.4s ease;
  }

  a:hover {
    color: #26b1db;
  }

  hr {
    margin: 5px 0px;
    border-color: #a3a3a3;
    border-style: solid;
  }
}

@media only screen and (max-width: 500px) {
  div.mobile-nav {
    width: auto;
    height: 60px;
    display: flex;

    label {
      display: block;
      cursor: pointer;
      margin-left: auto;
      margin-top: auto;
      margin-bottom: auto;
    }

    #toggle:checked + .menu {  // Displaying the Menu
      display: flex;
    }
  }

  nav h2 {
    font-size: 5vw;
    margin-top: auto;
    margin-bottom: auto;
    margin-right: auto;
  }

  div.nav-left {
    display: none;
  }

  div.nav-right {
    display: none;
  }
}

The problem is in this line:

#toggle:checked + .menu {
  display: flex;
}

When clicked on the hamburger icon, it doesn't display the menu, instead it keeps it's display to block.

Things I have tried:

  1. Changing the display to block when the the toggle checkbox gets clicked
  2. Setting display to none for unchecked and flex when checked as described here
  3. Putting .menu div and #toggle checkbox in a single div as Toni Michel Caubet said (This method does work, thanks but it works with a single element like an h1, not with a div containing many elements)
  4. Changing the combinator or grouping .menu div and #toggle checkbox after putting them in a div

EDIT:

At point 4, things started to work a bit. When I changed the + to a comma to group both of them, the menu appeared. But it didn't closed after clicking it again. I changed the display to block of the hamburger menu, and the checkbox was checked when the page got loaded. But after unchecking it, the checkbox disappeared but the menu didn't. I need a solution to this.

NOTE:

I want to make this entirely in CSS (Or SASS) without the use of JavaScript or jQuery

Thanks for the help!


Solution

  • Few things going on here.

    • As stated in the comments, the problem is that your checkbox isn't in the same container as your mobile nav.
    • You also have some <a> tag, closing as </button>, meaning that your html is incorrect.

    Solution

    • Keep the label of the checkbox where it is.
    • Move the checkbox to be a direct sibling of .menu.
      Then adjust your css to have #toggle as a selector and not div.mobile-nav #toggle.
      toggle is an id, you don't need to have a stronger specificity as it's a unique element.

    Short reminder of the selector: .foo + .foo2
    This selector will select every element with the class .foo2 if they are the next sibling of a element with the class .foo.
    Therefore, they have to be in the same parent node and be one next to each other.

    <nav>
      <h2>Nav Bar</h2>
      <div class="nav-left">
        <a>Home</a>
        <a>About</a>
        <a>Blog</a>
        <a>Contact</a>
      </div>
      <div class="nav-right">
        <a>Log In</a>
        <a>Sign Up</a>
      </div>
    
      <div class="mobile-nav">
        <label for="toggle"><h2>&#9776;</h2></label>
      </div>
    
      <-- I've moved the checkbox. Now the selector #toggle + .menu will work  -->
      <input type="checkbox" id="toggle"> 
    
      <div class="menu"> <!-- Mobile Menu -->
        <a>Home</a>
        <a>About</a>
        <a>Blog</a>
        <a>Contact</a>
        <hr>
        <a>Log In</button>
        <a>Sign Up</button>
      </div>
    </nav>
    

    // Fonts
    @import url("https://fonts.googleapis.com/css2?family=Mukta&display=swap");
    
    
    * {
      margin: 0px;
      padding: 0px;
    }
    
    // Navbar
    nav {
      width: auto;
      padding: 30px;
      background-color: #fafafa;
      display: flex;
      align-content: center;
      flex-wrap: wrap;
    
      h2 {
        color: #303030;
        font-family: "Mukta", sans-serif;
        margin-right: 30px;
      }
    }
    
    .nav-right {
      margin-left: auto;
    
      a {
        margin-right: 15px;
        margin-top: auto;
        font-family: "Mukta", sans-serif;
        text-decoration: none;
        color: rgb(109, 109, 109);
        transition: all 0.4s ease;
      }
    
      a:hover {
        color: #26b1db;
      }
    }
    
    .nav-left {
      display: flex;
      align-content: center;
    
      a {
        margin-right: 15px;
        margin-top: auto;
        font-family: "Mukta", sans-serif;
        text-decoration: none;
        color: rgb(109, 109, 109);
        transition: all 0.4s ease;
      }
    
      a:hover {
        color: #26b1db;
      }
    }
    
    div.mobile-nav {
      display: none;
    
      label {
        display: none;
      }
    
    }
    #toggle {
      display: none;
    }
    
    .menu {     // Mobile Menu Styling, Display is none
      width: 100vw;
      font-family: "Mukta", sans-serif;
      display: none;
      flex-direction: column;
      background-color: #fafafa;
      z-index: 1000;
    
      a {
        margin: 5px 0px;
        transition: all 0.4s ease;
      }
    
      a:hover {
        color: #26b1db;
      }
    
      hr {
        margin: 5px 0px;
        border-color: #a3a3a3;
        border-style: solid;
      }
    }
    
    @media only screen and (max-width: 500px) {
      div.mobile-nav {
        width: auto;
        height: 60px;
        display: flex;
    
        label {
          display: block;
          cursor: pointer;
          margin-left: auto;
          margin-top: auto;
          margin-bottom: auto;
        }
    
    
      }
      #toggle { //#toggle is on it's own now, it doesn't need more specificity
        visibility: hidden;
        height: 0;
        width: 0;
      }
      #toggle:checked + .menu {  // Displaying the Menu
        display: flex;
      }
      nav h2 {
        font-size: 5vw;
        margin-top: auto;
        margin-bottom: auto;
        margin-right: auto;
      }
    
      div.nav-left {
        display: none;
      }
    
      div.nav-right {
        display: none;
      }
    }