Sidenav menu that appears when click on button

Posted on

Problem

I have a side menu that appears when click on button, which works fine. But now I want to clean up my code, shorten it if possible. I was wondering if there is an easier and cleaner way to achieve the same result shown in the example below.

I would like to reduce the css and delete the “setTimeout” function from js code. I don’t want the side slide to depend on setTimeout. There are other ways to get the same result, but I’m not very good. Can anyone help me ? I’m new, sorry my dirty code, I’m trying to learn and stackoverflow helps with that.

var menu = document.querySelector(".mob_menu_button");
      function mobile_menu(e) {
        e.stopPropagation();
        var x = document.getElementById("mts_mobile_menu");
        if (!x.classList.contains("active")) {
          x.classList.add("active");
          menu.innerHTML = "<span>Close Menu<span>";
        } else {
          x.classList.add("side_hide");
          menu.innerHTML = "<span>Open menu</span>";

          setTimeout(function () {
            x.classList.remove("active");
            x.classList.remove("hide");
          }, 100);
        }
      }
      
      document.addEventListener("click", function (e) {
        var x = document.getElementById("mts_mobile_menu");
        if (e.target.id !== "mts_mobile_menu" && x.classList.contains("active")) {
          x.classList.add("hide");
          menu.innerHTML = "<span>Open menu</span>";

          setTimeout(function () {
            x.classList.remove("active");
            x.classList.remove("hide");
          }, 400);
        }
      });
* {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      /*Items menu*/
      .user_menu {
        display: flex;
        flex-direction: column;
      }

      /*Menu header info*/
      .display.name {
        font-size: 15px;
        font-weight: 500;
        color: #303238;
      }

      .display.mail {
        font-size: 13px;
        color: #3d5afe;
      }

      hr.solid {
        border-top: 1px solid #e0e0e0;
        margin: 10px 0px 10px 0px;
      }

      /*Text Link css*/
      .user_menu.item > a {
        display: flex;
        justify-content: flex-start;
        align-items: center;
        padding: 8px 0;
        font-size: 13px;
        color: #75777d;
      }

      .user_menu.item:hover > a {
        color: #2e323a;
      }

      /*Icon Button Toggle Menu*/
      .mob_menu_button {
       display: flex;
       align-content: center;
       justify-content: center;
       align-items: flex-end;
       width: 20%;
       background: #fff!important;
       font-weight: 500!important;
       position: absolute;
       top: 30px;
       right: 30px;
      }

      .icn_button {
        margin: 0;
        font-size: 14px;
      }

      .icn_button:before {
        margin: 0;
      }

      .icn_button:after {
        margin: 0;
      }

      /*Icon Items Menu*/
      .icn_menu:before,
      .icon_menu:after {
        margin: 0px;
        padding: 0px;
        font-size: 16px;
      }

      .icn_menu {
        margin-right: 10px;
        display: flex !important;
        align-items: center;
        justify-content: center;
        width: 22px;
        height: 22px;
      }

      /* User Menu For header website */
      .mts_mob_container {
        display: flex;
        position: fixed;
        z-index: 999;
        /* height: 100%; */
        top: 0;
        left: 0;
        width: 100%;
        background: #000000d6;
      }
      
     .mts_sidenav_box {
        display: block;
        width: 100%;
      }

      .mts_sidenav_content {
        display: none;
        padding: 20px;
        background-color: #fff;
        min-width: 160px;
        width: 280px;
        border-radius: 3px;
        overflow-x: hidden;
        overflow-y: auto;
        z-index: 999;
        position: relative;
        animation: animateFromLeft 0.4s;
      }

      @keyframes animateFromLeft {
        from {
          left: -500px;
          opacity: 0;
        }
        to {
          left: 0;
          opacity: 1;
        }
      }

      @keyframes animateToLeft {
        from {
          left: 0;
          opacity: 1;
        }
        to {
          left: -500px;
          opacity: 0;
        }
      }

    .active {
      display: block !important;
      height: 100vh;
      overflow: hidden;
      width: 75%;
   }

      .mts_sidenav_content.hide {
        animation: animateToLeft 0.8s;
      }
<button onclick="mobile_menu(event)" class="mob_menu_button">Open menu</button>

      <div class="mts_mob_container">
         <div id="mts_mobile_menu" class="mts_sidenav_content"> 
          <div class="mts_sidenav_box">
          
            <div class="user_menu header">
              <span class="display name">Hello User...</span>
              <span class="display mail">display_email</span>
            </div>

            <hr class="solid" />

            <div class="user_menu item">
              <a href="/account">
                <i class="icn_menu fa-regular fa-user">1</i>
                <span class="link_text">Dashboard</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="ordini">
                <i class="icn_menu fa-regular fa-basket-shopping">2</i>
                <span class="link_text">I miei ordini</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="libreria">
                <i class="icn_menu fa-regular fa-cloud-arrow-down">3</i>
                <span class="link_text">Downloads</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="impostazioni">
                <i class="icn_menu fa-regular fa-gear">4</i>
                <span class="link_text">Impostazioni</span>
              </a>
            </div>

            <div class="user_menu item">
              <a href="wp-login.php?action=logout">
                <i class="icn_menu fa-regular fa-arrow-right-from-bracket">5</i>
                <span class="link_text">Logout</span>
              </a>
            </div>
          </div>
        </div>
      </div>

Solution

From a short review;

  • x is not an evocative name,

  • JavaScript is lowerCamelCase so mobile_menu -> mobileMenu

  • Even mobileMenu is not a great name, it does not tell me what it does

  • var menu should be const menuButton

  • This is copy pasted, you should have a function that takes and element, and a delay;

        function delayExecution(e, delay){
          setTimeout(function () {
            e.classList.remove("active");
            e.classList.remove("hide");
          }, delay);
        }
    
  • I am not a good reviewer of CSS, but you are not violating the cardinal rule, so seems okay to me

  • Avoid wiring functions in HTML like this; onclick="mobile_menu(event)", use addEventListener like for document

Leave a Reply

Your email address will not be published. Required fields are marked *