Home > Mobile >  How to prevent page scroll and closing menu when click outside menu container
How to prevent page scroll and closing menu when click outside menu container

Time:05-22

Edit with solution


I have a sidebar menu that appears and disappears when I click on the button. Two problems were occurring in the menu, here they are listed below:

  1. The menu closes by clicking outside the #mobile_menu div and that's what I want. However the menu also closes by clicking inside div #mobile_menu, I don't want that to happen, clicking inside this div the menu should not close.

  2. The second aspect is that when the menu is open, the back page is free to scroll up and down, is there any way to prevent this ?

I solved these problems thanks to the intervention of @moronator

var mobileMenu = document.querySelector("#toggle_menu");
    function mobile_menu(e) {
        e.stopPropagation();
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        var z = document.getElementsByTagName("body")[0];
        
        // For var x - Show & Hide Menu
        if (!x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y Show & Hide Overlay
        if (!y.classList.contains("on")) {
          y.classList.toggle("on");
        } else {
          y.classList.remove("on");
        }
        
        // For var z Prevent Page scroll with overflow
         if (!z.classList.contains("ppscroll")) {
          z.classList.toggle("ppscroll");
        } else {
          z.classList.remove("ppscroll"); 
        }
        
    }
     
        // Close Menu clicking on container_overlay
        document.getElementById("container_overlay").addEventListener("click", function (e) {
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        var z = document.getElementsByTagName("body")[0];
        
        // For var x
        if (e.target.id !== "mobile_menu" && x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y
        if (e.target.id !== "mobile_menu" && y.classList.contains("on")) {
          y.classList.toggle("on");
        }
        // For var z
        if (e.target.id !== "mobile_menu" && z.classList.contains("ppscroll")) {
          z.classList.toggle("ppscroll");
        }
      });
/*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;
}

/*Logout Header*/
.logout_header {    
    display: flex;
    justify-content: space-between;
}

.mob {
    display: flex;
    width: 49.5%;
    justify-content: center;
    background: #fbfbfb;
    border: 1px solid #eee;
    border-radius: 4px;
    padding: 4px;
}

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

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

/*Icon Button Toggle Menu*/
#toggle_menu {
    width: 20%;
    color: #000;
    position: absolute;
    right: 20px;
    top: 20px;
}

.icn_toggle, .icn_toggle::before, .icn_toggle::after {
    margin: 0;
    z-index: 1000;
    font-size: 24px;
}

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

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

/* User Menu For header website */
#container_overlay {
    visibility: hidden;
    position: fixed;
    z-index: 998;
    top: 0;
    left: 0;
    width: 100%;
    background: #000000d6;
    opacity: 0;
    transition: 0.3s;
    height: 100vh;
}
      
#container_overlay.on {
    visibility: visible;
    opacity: 1;

}
      
.content_menu {
    display: block;
    width: 100%;
}

#mobile_menu {
    top: 0;
    left: -100%;
    padding: 20px;
    background-color: #fff;
    min-width: 160px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 999;
    position: fixed;
    width: 75%;
    height: 100vh;
    transition: .3s;
}

#mobile_menu.show {
    left: 0;
}

.ppscroll {
    overflow: hidden;
}

/* Dropdown Button */
.dropbtn {
  background-color: #04AA6D;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
  position: relative;
  display: inline-block;
}

/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #ddd;}

/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {display: block;}

/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {background-color: #3e8e41;}
<div onclick="mobile_menu(event)" id="toggle_menu"><i >Open Menu</i></div>

    <div id="mobile_menu"> 
        <div >
            <div >
              <span >Ciao [display_name]</span>
              <span >[display_email]</span>
            </div>

            <div >
              <a  href="#"><span>Login</span></a>
                
              <a  href="#"> <span>Singup</span></a>
            </div>

            <hr  />
            
            <div >
              <a href="#">
                <i ></i>
                <span >Dashboard</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >I miei ordini</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Downloads</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Impostazioni</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Logout</span>
              </a>
            </div>
        </div>  
    </div>

<div id="container_overlay"></div>


Original code with errors listed

var mobileMenu = document.querySelector("#toggle_menu");
    function mobile_menu(e) {
        e.stopPropagation();
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        
        // For var x
        if (!x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y
        if (!y.classList.contains("on")) {
          y.classList.toggle("on");
        } else {
          y.classList.remove("on");
        }
    }
     
        // Close Menu clicking on container_overlay
        document.addEventListener("click", function (e) {
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        
        // For var x
        if (e.target.id !== "mobile_menu" && x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y
        if (e.target.id !== "mobile_menu" && y.classList.contains("on")) {
          y.classList.toggle("on");
        }
        
      }); 
/*Items menu*/
.user_menu {
    display: flex;
    flex-direction: column;
    cursor: not-allowed;
    pointer-events: none !important;
    border: 1px solid red;
}

.error {
color: red;
}

/*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;
}

/*Logout Header*/
.logout_header {    
    display: flex;
    justify-content: space-between;
}

.mob {
    display: flex;
    width: 49.5%;
    justify-content: center;
    background: #fbfbfb;
    border: 1px solid #eee;
    border-radius: 4px;
    padding: 4px;
}

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

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

/*Icon Button Toggle Menu*/
#toggle_menu {
    display: flex;
    align-content: flex-end;
    justify-content: center;
    align-items: flex-end;
    width: 20%;
    color: #000;
    position: absolute;
    top 20px;
    right: 20px;
}

.icn_toggle, .icn_toggle::before, .icn_toggle::after {
    margin: 0;
    z-index: 1000;
    font-size: 24px;
}

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

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

/* User Menu For header website */
#container_overlay {
    visibility: hidden;
    position: fixed;
    z-index: 998;
    top: 0;
    left: 0;
    width: 100%;
    background: #000000b8;
    opacity: 0;
    transition: 0.3s;
    height: 100vh;
}
      
#container_overlay.on {
    visibility: visible;
    opacity: 1;

}
      
.content_menu {
    display: block;
    width: 100%;
}

#mobile_menu {
    top: 0;
    left: -100%;
    padding: 20px;
    background-color: #fff;
    min-width: 160px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 999;
    position: fixed;
    width: 75%;
    height: 100vh;
    transition: .3s;
}

#mobile_menu.show {
    left: 0;
}
<div onclick="mobile_menu(event)" id="toggle_menu"><i ></i>Menu</div>

    <div id="mobile_menu"> 
        <div >

            <div >
              <span >Hello [display_name]</span>
              <span >[display_email]</span>
              <span >clicking here closes the menu, it shouldn't happen.
            </div>
   
            <div >
              <a  href="#"><span>Login</span></a>
                
              <a  href="#"> <span>Singup</span></a>
            </div>
            
            <hr  />
            
            <div >
              <a href="#">
                <i ></i>
                <span >Dashboard</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >I miei ordini</span>
              </a>
            </div>

            <div >
              <a href="libreria">
                <i ></i>
                <span >Downloads</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Impostazioni</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Logout</span>
              </a>
            </div>
 
        </div>
    </div>

<div id="container_overlay"></div>

CodePudding user response:

Just add the event listener to your overlay container instead of your whole document:

var mobileMenu = document.querySelector("#toggle_menu");
    function mobile_menu(e) {
        e.stopPropagation();
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        
        // For var x
        if (!x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y
        if (!y.classList.contains("on")) {
          y.classList.toggle("on");
        } else {
          y.classList.remove("on");
        }
    }
     
        // Close Menu clicking on container_overlay
        // ------- I JUST CHANGED THE FOLLOWING LINE -------
        document.getElementById("container_overlay").addEventListener("click", function (e) {
        var x = document.getElementById("mobile_menu");
        var y = document.getElementById("container_overlay");
        
        // For var x
        if (e.target.id !== "mobile_menu" && x.classList.contains("show")) {
          x.classList.toggle("show");
          mobileMenu.innerHTML = '<i >Open Menu</i>';
        }
        // For var y
        if (e.target.id !== "mobile_menu" && y.classList.contains("on")) {
          y.classList.toggle("on");
        }
        
      }); 
/*Items menu*/
.user_menu {
    display: flex;
    flex-direction: column;
    cursor: not-allowed;
    pointer-events: none !important;
    border: 1px solid red;
}

.error {
color: red;
}

/*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;
}

/*Logout Header*/
.logout_header {    
    display: flex;
    justify-content: space-between;
}

.mob {
    display: flex;
    width: 49.5%;
    justify-content: center;
    background: #fbfbfb;
    border: 1px solid #eee;
    border-radius: 4px;
    padding: 4px;
}

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

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

/*Icon Button Toggle Menu*/
#toggle_menu {
    display: flex;
    align-content: flex-end;
    justify-content: center;
    align-items: flex-end;
    width: 20%;
    color: #000;
    position: absolute;
    top 20px;
    right: 20px;
}

.icn_toggle, .icn_toggle::before, .icn_toggle::after {
    margin: 0;
    z-index: 1000;
    font-size: 24px;
}

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

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

/* User Menu For header website */
#container_overlay {
    visibility: hidden;
    position: fixed;
    z-index: 998;
    top: 0;
    left: 0;
    width: 100%;
    background: #000000b8;
    opacity: 0;
    transition: 0.3s;
    height: 100vh;
}
      
#container_overlay.on {
    visibility: visible;
    opacity: 1;

}
      
.content_menu {
    display: block;
    width: 100%;
}

#mobile_menu {
    top: 0;
    left: -100%;
    padding: 20px;
    background-color: #fff;
    min-width: 160px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 999;
    position: fixed;
    width: 75%;
    height: 100vh;
    transition: .3s;
}

#mobile_menu.show {
    left: 0;
}
<div onclick="mobile_menu(event)" id="toggle_menu"><i ></i>Menu</div>

    <div id="mobile_menu"> 
        <div >

            <div >
              <span >Hello [display_name]</span>
              <span >[display_email]</span>
              <span >clicking here closes the menu, it shouldn't happen.
            </div>
   
            <div >
              <a  href="#"><span>Login</span></a>
                
              <a  href="#"> <span>Singup</span></a>
            </div>
            
            <hr  />
            
            <div >
              <a href="#">
                <i ></i>
                <span >Dashboard</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >I miei ordini</span>
              </a>
            </div>

            <div >
              <a href="libreria">
                <i ></i>
                <span >Downloads</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Impostazioni</span>
              </a>
            </div>

            <div >
              <a href="#">
                <i ></i>
                <span >Logout</span>
              </a>
            </div>
 
        </div>
    </div>

<div id="container_overlay"></div>

  • Related