skip to Main Content

I have the following problem: When I click on the label-"button" (hamburger menu) I have to double to click to show the menu the second time around.

I think is a conflict beween CSS and jQuery.

The intended code behavior is the following: When you click #NavDark I want to hide .MainMenu and #NavDark itself, when you click the label I want to show them both.

$("#NavDark").click(function() {
  $(".MainMenu").hide();
  $("#NavDark").hide();

});


$("#toggle").click(function() {
  $(".MainMenu,#NavDark").show();

});
.ButtonMenu label:checked~.MainMenu {
  display: block !important;
}

.ButtonMenu #toggle {
  display: none;
}

.ButtonMenu label {
  font-size: 40px;
  color: #000;
  cursor: pointer;
  z-index: 8;
  display: inline-block !important;
}

.MainMenu {
  position: fixed;
  top: 0;
  width: 320px;
  background-color: #222;
  color: #fff;
  transition: all .4s ease;
  overflow-y: auto;
  height: 100vh;
  box-shadow: 0 0 2px #000;
  z-index: 8;
  opacity: 0;
  right: -320px;
}

#toggle:checked~.MainMenu {
  opacity: 1;
  transform: translateX(-100%);
}

#NavDark {
  width: 100%;
  right: 0;
  top: 0;
  height: 100vh;
  position: fixed;
  background-color: rgba(0, 0, 0, .5);
  opacity: 0;
  z-index: -1;
}

#toggle:checked~#NavDark {
  z-index: 100;
  opacity: 1;
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="ButtonMenu">

  <input id='toggle' type='checkbox' />
  <label for='toggle'>
<img src="/img/image 8.png" alt="hamburger icon">
</label>

  <div id="NavDark">


  </div>
  <div class='MainMenu'>

    {{ range .Site.Menus.main }}

    <a href="{{ .URL }}" class="navbar-item" title="{{ .Name }}">             {{ .Name }}</a> {{ end }}

  </div>
</div>

I need help on how to make the label only needing one click each time to show the menu.

3

Answers


  1. It seems like the issue might be related to the order of operations in your JavaScript. The click event for #toggle is showing both .MainMenu and #NavDark, but the click event for #NavDark is only hiding them.

    To solve this issue, you can modify your JavaScript to toggle the visibility of both elements when #toggle is clicked.

    updated js

    $(document).ready(function() {
      $("#toggle").click(function() {
        $(".MainMenu, #NavDark").toggle();
      });
    
      $("#NavDark").click(function() {
        $(".MainMenu, #NavDark").hide();
      });
    });
    
    Login or Signup to reply.
  2. This is indeed a CSS-jQuery compatibility issiue. In your CSS, visibility of .MainMenu and #NavDark is controlled by wether the checkbox is checked:

    #toggle:checked~.MainMenu {
      opacity: 1;
      transform: translateX(-100%);
    }
    #toggle:checked~#NavDark {
      z-index: 100;
      opacity: 1;
      display: block;
    }
    

    In your JS, however, visibility of the two elements is controlled (internally) via the style="" display value. Now the following happens:

    • Initially, the checkbox is unchecked, and the inline style attribute is missing, which means the two elements have their default value of display:block, but are moved offscreen by the CSS.
    • Now we click the label. The checkbox gets checked, and the CSS relocates them onscreen. The JS click handler of #toggle runs, but because the style attribute already (implicitly) is block, nothing happens.
    • Now we click #NavDark to close the menu. The JS handler of #NavDark runs, and sets the inline style value to display:hidden, so they hide. The ckeckbox hasn’t been altered by either the click nor JS code, so it remains checked.
    • Now we click the label again. The checkbox gets toggled, so it is now unchecked, and as a result CSS moves the (would-be) position of .MainMenu and #NavDark to be ofscreen. the JS handler runs, and removes display:none, but the two elements are offscreen and so don’t display.
    • during the second click, the JS does nothing, as the style attribute says they’re already visible, but the checkbox gets checked, so it moves the two elements back onscreen.

    Additionally, your z-index values appear to be off, which means that .MainMenu displays behind #NavDark and is unclickable.

    As for a fix, you could alter the JS handler so it additionally unchecks the checkbox:

    $("#NavDark").click(function() {
      $(".MainMenu").hide();
      $("#NavDark").hide();
      $("#toggle").prop("checked", false);
    });
    
    $("#NavDark").click(function() {
      $(".MainMenu").hide();
      $("#NavDark").hide();
      $("#toggle").prop("checked", false);
    });
    
    
    $("#toggle").click(function() {
      $(".MainMenu,#NavDark").show();
    
    });
    .ButtonMenu label:checked ~ .MainMenu {
        
        display: block !important;
        
    }
    .ButtonMenu #toggle {
    
    display:none;
    
    }
    .ButtonMenu label {
        font-size: 40px;
        color: #000;
        cursor: pointer;
        z-index: 8;
        display: inline-block !important;
    }
    
    
    
    .MainMenu {
        position: fixed;
        top: 0;
        width: 320px;
        background-color: #222;
        color: #fff;
        transition: all .4s ease;
        overflow-y: auto;
        height: 100vh;
        box-shadow: 0 0 2px #000;
        z-index: 120;/* new z-index to reflect  #NavDark */
        opacity:0; 
        right:-320px;
    
      
    }
    
    
    #toggle:checked ~ .MainMenu {
        opacity:1 ;
      transform: translateX(-100%);
    
    }
    
    
    #NavDark {
        width: 100%;
        right: 0;
        top: 0;
        height: 100vh;
        position: fixed;
        background-color: rgba(0,0,0,.5);
        opacity: 0;
        z-index: -1;
    
    }
    
    #toggle:checked ~ #NavDark{
        z-index: 100;
        opacity: 1;
        display: block;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="ButtonMenu">
      <input id='toggle' type='checkbox' />
      <label for='toggle'>
    <img src="/img/image 8.png" alt="hamburger">
    </label>
      <div id="NavDark"></div>
      <div class='MainMenu'>
        {{ range .Site.Menus.main }}
    
        <a href="{{ .URL }}" class="navbar-item" title="{{ .Name }}">             {{ .Name }}</a> {{ end }}
    
      </div>
    </div>

    Or you could ditch the checkbox entirely and have the visibility be controlled by the style attribute:

    $("#NavDark").click(function() {
      $(".MainMenu").hide();
      $("#NavDark").hide();
    });
    
    
    $("#toggle").click(function() {
      $(".MainMenu,#NavDark").show();
    
    });
    .ButtonMenu #toggle {
      display: none;
    }
    
    .ButtonMenu label {
      font-size: 40px;
      color: #000;
      cursor: pointer;
      z-index: 8;
      display: inline-block !important;
    }
    
    .MainMenu {
      position: fixed;
      top: 0;
      width: 320px;
      background-color: #222;
      color: #fff;
      transition: all .4s ease;
      overflow-y: auto;
      height: 100vh;
      box-shadow: 0 0 2px #000;
      z-index: 8;
      right: 0;
    }
    
    #NavDark {
      width: 100%;
      right: 0;
      top: 0;
      height: 100vh;
      position: fixed;
      background-color: rgba(0, 0, 0, .5);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="ButtonMenu">
      <label id='toggle'>
    <img src="/img/image 8.png" alt="hamburger">
    </label>
    
      <div id="NavDark" style="display:none">
      </div>
      <div class='MainMenu' style="display:none">
    
        {{ range .Site.Menus.main }}
    
        <a href="{{ .URL }}" class="navbar-item" title="{{ .Name }}">             {{ .Name }}</a> {{ end }}
    
      </div>
    </div>
    Login or Signup to reply.
    • You don’t necessarily need JS at all.
    • Rename better your attributes ID values.
    • Better nest your markup. Keep the input in root on DOM top.
    • Use :checked to translare a single element #menu-wrapper
    • Use CSS pointer-events to remove preserve or pass-through clicks and other pointer events
    #btn-hamburger {
      font-size: 2.4rem;
      z-index: 8;
      display: inline-block !important;
    }
    
    [for="menu-toggle"] {
      cursor: pointer;
    }
    
    #menu-wrapper {
      position: fixed;
      width: 100%;
      height: 100dvh; /* use dvh units */
      left: 0;
      top: 0;
      z-index: 100;
      background-color: rgba(0, 0, 0, .5);
      transition: translate 0.4s, opacity 0.4s;
      translate: 100% 0%;
      opacity: 0;
      pointer-events: none; /* let clicks pass-through */
    }
    
    #menu {
      position: absolute;
      right: 0;
      width: 320px;
      height: 100dvh;   /* use dvh units */
      overflow-y: auto;
      box-shadow: 0 0 2px #000;
      background-color: #222;
      color: #fff;
      pointer-events: auto; /* preserve clicks */
    }
    
    #menu-toggle {
      display: none;
    }
    
    #menu-toggle:checked ~ #menu-wrapper {
      translate: 0% 0%;
      opacity: 1;
    }
    <input id="menu-toggle" type="checkbox" />
    <label id="btn-hamburger" for="menu-toggle">hamburger icon</label>
    
    <div id="menu-wrapper">
      <div id="menu">
        <label for="menu-toggle" title="Close menu">CLOSE &times;</label>
        <h3>Menu...</h3>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search