skip to Main Content

I designed some CSS rules for a responsive navigation menu which allows me to add sub-menus, but each sub-menu requires the creation of new CSS selectors. I want to style the menu and sub-menus once so that a beginner user does not need to add any new CSS selectors in order to create nested submenus.

const MenuButton = document.querySelector(".nav-menu-button");
const Navigation = document.querySelector(".nav");

let MenuOpen = false;

MenuButton.addEventListener("click", () => {
  switch (!MenuOpen) {
    case true:
      MenuButton.classList.add("open");
      Navigation.setAttribute("data-visible", "true")
      MenuOpen = true;
      break;
    default:
      MenuButton.classList.remove("open");
      Navigation.setAttribute("data-visible", "false")
      MenuOpen = false;
      break;
  }
});
@font-face {
  font-family: "Roboto";
  font-style: normal;
  src: url("../Fonts/Roboto.ttf") format("truetype");
}

* {
  font-family: "Roboto";
  font-size: 20px;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  direction: rtl;
}

.logo {
  z-index: 10;
  position: relative;
}

.header {
  float: center;
  background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
  border-radius: 10px;
  box-shadow: 1px 2px 4px #000000;
  color: white;
  width: 100%;
  height: 100px;
  padding-left: 0px;
  padding-right: 10px;
  padding-top: 40px;
  text-align: right;
  text-shadow: 0px 2px 2px #000000;
}

.nav {
  list-style: none;
  display: flex;
  gap: 24px;
}

.nav li a {
  text-decoration: none;
  font-size: 28px;
  color: #f3b238;
  display: inline-block;
  width: 100%;
  position: relative;
}

.nav li a:hover {
  color: #fff;
}

.nav li a::after {
  content: "";
  width: 0%;
  height: 4px;
  background-color: #fff;
  position: absolute;
  left: 0px;
  bottom: -5px;
  border-radius: 5px;
  transition: all 0.7s ease;
}

.nav li a:hover::after {
  width: 100%;
}

@media (max-width: 769px) {
  .nav {
    position: fixed;
    inset: 0;
    background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
    flex-direction: column;
    align-items: center;
    /*padding-top: 150px;*/
    padding-top: 70px;
    transform: translateX(100%);
    transition: all 0.7s ease;
  }

  .nav[data-visible=true] {
    transform: translateX(0%);
  }

  .nav-menu-button {
    position: absolute;
    display: flex;
    z-index: 10;
    justify-content: center;
    align-items: center;
    height: 80px;
    width: 80px;
    right: -10px;
    top: -10px;
    cursor: pointer;
    transition: all 0.7s ease-in-out;
  }

  .nav-menu-line {
    width: 50px;
    height: 6px;
    background-color: #d0fd66;
    border-radius: 5px;
    transition: all 0.7s ease-in-out;
  }

  .nav-menu-line::before,
  .nav-menu-line::after {
    content: "";
    position: absolute;
    width: 50px;
    height: 6px;
    background-color: #d0fd66;
    border-radius: 5px;
    transition: all 0.7s ease-in-out;
  }

  .nav-menu-line::before {
    transform: translateY(-16px);
  }

  .nav-menu-line::after {
    transform: translateY(16px);
  }

  .nav-menu-button.open .nav-menu-line {
    transform: translateX(-50px);
    background: transparent;
  }

  .nav-menu-button.open .nav-menu-line::before {
    transform: rotate(45deg) translate(35px, -35px);
  }

  .nav-menu-button.open .nav-menu-line::after {
    transform: rotate(-45deg) translate(35px, 35px);
  }
}
<div class="logo" role="img">
  <img src="Images/Logo.png" height="100" style="width:auto; float:left;" />
</div>
<header class="header">
  <div class="nav-menu-button">
    <div class="nav-menu-line"></div>
  </div>
  <nav class="nav" data-visible="false" role="navigation">
    <li>
      <a href="#">Home</a>
    </li>
    <li>
      <a href="#">Goods</a>
    </li>
  </nav>
</header>

If your answer solves my problem (by using this multi-level dropdown style), I will accept and score it. Please use the Snippet editor to respond to my question.

2

Answers


  1. If you want to allow the addition of submenus without creating new selectors in SASS, you can modify your HTML structure and update the SASS styles accordingly.

    Here’s an updated version of your code that allows the addition of submenus:

    SASS:

    @font-face {
      font-family: "Roboto";
      font-style: normal;
      src: url("../Fonts/Roboto.ttf") format("truetype");
    }
    
    * {
      font-family: "Roboto";
      font-size: 20px;
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      direction: rtl;
    }
    
    .logo {
      z-index: 10;
      position: relative;
    }
    
    .header {
      float: center;
      background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
      border-radius: 10px;
      box-shadow: 1px 2px 4px #000000;
      color: white;
      width: 100%;
      height: 100px;
      padding-left: 0px;
      padding-right: 10px;
      padding-top: 40px;
      text-align: right;
      text-shadow: 0px 2px 2px #000000;
    }
    
    .nav {
      list-style: none;
      display: flex;
      gap: 24px;
    }
    
    .nav li {
      position: relative;
    }
    
    .nav li a {
      text-decoration: none;
      font-size: 28px;
      color: #f3b238;
      display: inline-block;
      width: 100%;
      position: relative;
    }
    
    .nav li a:hover {
      color: #fff;
    }
    
    .nav li a::after {
      content: "";
      width: 0%;
      height: 4px;
      background-color: #fff;
      position: absolute;
      left: 0px;
      bottom: -5px;
      border-radius: 5px;
      transition: all 0.7s ease;
    }
    
    .nav li a:hover::after {
      width: 100%;
    }
    
    @media (max-width: 769px) {
      .nav {
        position: fixed;
        inset: 0;
        background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
        flex-direction: column;
        align-items: center;
        padding-top: 150px;
        transform: translateX(100%);
        transition: all 0.7s ease;
      }
    
      .nav[data-visible="true"] {
        transform: translateX(0%);
      }
    
      .nav-menu-button {
        position: absolute;
        display: flex;
        z-index: 10;
        justify-content: center;
        align-items: center;
        height: 80px;
        width: 80px;
        right: -10px;
        top: -10px;
        cursor: pointer;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line {
        width: 50px;
        height: 6px;
        background-color: #d0fd66;
        border-radius: 5px;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line::before,
      .nav-menu-line::after {
        content: "";
        position: absolute;
        width: 50px;
        height: 6px;
        background-color: #d0fd66;
        border-radius: 5px;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line::before {
        transform: translateY(-16px);
      }
    
      .nav-menu-line::after {
        transform: translateY(16px);
      }
    
      .nav-menu-button.open .nav-menu-line {
        transform: translateX(-50px);
        background: transparent;
      }
    
      .nav-menu-button.open .nav-menu-line::before {
        transform: rotate(45deg) translate(35px, -35px);
      }
    
      .nav-menu-button.open .nav-menu-line::after {
        transform: rotate(-45deg) translate(35px, 35px);
      }
    }
    

    HTML:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Pasha-Piano</title>
      <link rel="stylesheet" href="SCSS/AppStyle.css">
      <link rel="stylesheet" href="SCSS/AppStyle.scss" media="(max-width:769px)">
      <link rel="stylesheet" href="Script.js">
    </head>
    
    <body>
      <div class="logo" role="img">
        <img src="Images/Logo.png" height="100" style="width:auto; float:left;" />
      </div>
      <header class="header">
        <div class="nav-menu-button">
          <div class="nav-menu-line"></div>
        </div>
        <nav class="nav" data-visible="false" role="navigation">
          <ul class="nav-list">
            <li><a href="#">Home</a></li>
            <li>
              <a href="#">Goods</a>
              <ul class="sub-menu">
                <li><a href="#">Submenu 1</a></li>
                <li><a href="#">Submenu 2</a></li>
                <li><a href="#">Submenu 3</a></li>
              </ul>
            </li>
          </ul>
        </nav>
      </header>
      <script src="Script.js"></script>
    </body>
    
    </html>
    

    With this updated code, you can add submenus by nesting <ul class="sub-menu"> inside the parent <li>. The SASS styles have been updated to accommodate the submenus, and no additional selectors are required in SASS to style them.

    Login or Signup to reply.
  2. Below is an updated version of your code that achieves this:

    <div class="logo" role="img">
      <img src="Images/Logo.png" height="100" style="width:auto; float:left;" />
    </div>
    <header class="header">
      <div class="nav-menu-button">
        <div class="nav-menu-line"></div>
      </div>
      <nav class="nav" data-visible="false" role="navigation">
        <ul class="nav-menu">
          <li>
            <a href="#">Home</a>
          </li>
          <li>
            <a href="#">Goods</a>
            <ul class="sub-menu">
              <li>
                <a href="#">Sub-Item 1</a>
              </li>
              <li>
                <a href="#">Sub-Item 2</a>
              </li>
            </ul>
          </li>
        </ul>
      </nav>
    </header>
    

    And here’s the updated CSS code:

    * {
      font-family: "Roboto";
      font-size: 20px;
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      direction: rtl;
    }
    
    .logo {
      z-index: 10;
      position: relative;
    }
    
    .header {
      float: center;
      background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
      border-radius: 10px;
      box-shadow: 1px 2px 4px #000000;
      color: white;
      width: 100%;
      height: 100px;
      padding-left: 0px;
      padding-right: 10px;
      padding-top: 40px;
      text-align: right;
      text-shadow: 0px 2px 2px #000000;
    }
    
    .nav {
      list-style: none;
      display: flex;
      gap: 24px;
    }
    
    .nav .nav-menu {
      position: relative;
    }
    
    .nav .nav-menu > li {
      position: relative;
    }
    
    .nav .nav-menu > li > a {
      text-decoration: none;
      font-size: 28px;
      color: #f3b238;
      display: inline-block;
      width: 100%;
      position: relative;
    }
    
    .nav .nav-menu > li > a:hover {
      color: #fff;
    }
    
    .nav .nav-menu > li > a::after {
      content: "";
      width: 0%;
      height: 4px;
      background-color: #fff;
      position: absolute;
      left: 0px;
      bottom: -5px;
      border-radius: 5px;
      transition: all 0.7s ease;
    }
    
    .nav .nav-menu > li > a:hover::after {
      width: 100%;
    }
    
    .nav .nav-menu .sub-menu {
      display: none;
      position: absolute;
      top: 100%;
      left: 0;
      padding-top: 10px;
      background-color: #9472ff;
      border-radius: 10px;
      box-shadow: 1px 2px 4px #000000;
    }
    
    .nav .nav-menu .sub-menu li {
      display: block;
    }
    
    .nav .nav-menu .sub-menu li a {
      font-size: 20px;
      color: #f3b238;
      display: block;
      padding: 10px 20px;
      text-decoration: none;
    }
    
    .nav .nav-menu .sub-menu li a:hover {
      color: #fff;
    }
    
    .nav .nav-menu > li:hover .sub-menu {
      display: block;
    }
    
    @media (max-width: 769px) {
      .nav {
        position: fixed;
        inset: 0;
        background: linear-gradient(to top, #9472ff 2%, #3d00ff 98%) center/100%;
        flex-direction: column;
        align-items: center;
        padding-top: 70px;
        transform: translateX(100%);
        transition: all 0.7s ease;
      }
    
      .nav[data-visible="true"] {
        transform: translateX(0%);
      }
    
      .nav-menu-button {
        position: absolute;
        display: flex;
        z-index: 10;
        justify-content: center;
        align-items: center;
        height: 80px;
        width: 80px;
        right: -10px;
        top: -10px;
        cursor: pointer;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line {
        width: 50px;
        height: 6px;
        background-color: #d0fd66;
        border-radius: 5px;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line::before,
      .nav-menu-line::after {
        content: "";
        position: absolute;
        width: 50px;
        height: 6px;
        background-color: #d0fd66;
        border-radius: 5px;
        transition: all 0.7s ease-in-out;
      }
    
      .nav-menu-line::before {
        transform: translateY(-16px);
      }
    
      .nav-menu-line::after {
        transform: translateY(16px);
      }
    
      .nav-menu-button.open .nav-menu-line {
        transform: translateX(-50px);
        background: transparent;
      }
    
      .nav-menu-button.open .nav-menu-line::before {
        transform: rotate(45deg) translate(35px, -35px);
      }
    
      .nav-menu-button.open .nav-menu-line::after {
        transform: rotate(-45deg) translate(35px, 35px);
      }
    }
    

    With these changes, you can now add sub-menus simply by nesting <ul class="sub-menu"> within the appropriate <li> element. The CSS will take care of the styling and display of the sub-menus when the parent menu item is hovered.

    I hope this solution meets your requirements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search