javascript - 单击菜单容器外部时如何防止页面滚动和关闭菜单

标签 javascript html css menu sidebar

使用解决方案进行编辑


我有一个侧边栏菜单,当我单击该按钮时,该菜单会出现并消失。菜单中出现了两个问题,如下所列:

  1. 通过单击 #mobile_menu div 外部关闭菜单,这就是我想要的。但是,通过单击 div #mobile_menu 内部也会关闭菜单,我不希望发生这种情况,单击此 div 内部菜单不应关闭。

  2. 第二个方面是,当菜单打开时,后台页面可以随意上下滚动,有什么办法可以防止这种情况发生吗?

感谢@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 class="icn_toggle fa-solid fa-xmark">Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars">Open Menu</i></div>

    <div id="mobile_menu"> 
        <div class="content_menu">
            <div class="user_menu header">
              <span class="display name">Ciao [display_name]</span>
              <span class="display mail">[display_email]</span>
            </div>

            <div class="logout_header">
              <a class="mob btn-login" href="#"><span>Login</span></a>
                
              <a class="mob btn-singup" href="#"> <span>Singup</span></a>
            </div>

            <hr class="solid" />
            
            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-user"></i>
                <span class="link_text">Dashboard</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-basket-shopping"></i>
                <span class="link_text">I miei ordini</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-cloud-arrow-down"></i>
                <span class="link_text">Downloads</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-gear"></i>
                <span class="link_text">Impostazioni</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-arrow-right-from-bracket"></i>
                <span class="link_text">Logout</span>
              </a>
            </div>
        </div>  
    </div>

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


列出了错误的原始代码

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 class="icn_toggle fa-solid fa-xmark">Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars"></i>Menu</div>

    <div id="mobile_menu"> 
        <div class="content_menu">

            <div class="user_menu header">
              <span class="display name">Hello [display_name]</span>
              <span class="display mail">[display_email]</span>
              <span class="error">clicking here closes the menu, it shouldn't happen.
            </div>
   
            <div class="logout_header">
              <a class="mob btn-login" href="#"><span>Login</span></a>
                
              <a class="mob btn-singup" href="#"> <span>Singup</span></a>
            </div>
            
            <hr class="solid" />
            
            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-user"></i>
                <span class="link_text">Dashboard</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-basket-shopping"></i>
                <span class="link_text">I miei ordini</span>
              </a>
            </div>

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

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-gear"></i>
                <span class="link_text">Impostazioni</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-arrow-right-from-bracket"></i>
                <span class="link_text">Logout</span>
              </a>
            </div>
 
        </div>
    </div>

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

最佳答案

只需将事件监听器添加到覆盖容器而不是整个文档:

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 class="icn_toggle fa-solid fa-xmark">Close Menu</i>';
        } else {
          x.classList.remove("show");
          mobileMenu.innerHTML = '<i class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars">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 class="icn_toggle fa-solid fa-bars"></i>Menu</div>

    <div id="mobile_menu"> 
        <div class="content_menu">

            <div class="user_menu header">
              <span class="display name">Hello [display_name]</span>
              <span class="display mail">[display_email]</span>
              <span class="error">clicking here closes the menu, it shouldn't happen.
            </div>
   
            <div class="logout_header">
              <a class="mob btn-login" href="#"><span>Login</span></a>
                
              <a class="mob btn-singup" href="#"> <span>Singup</span></a>
            </div>
            
            <hr class="solid" />
            
            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-user"></i>
                <span class="link_text">Dashboard</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-basket-shopping"></i>
                <span class="link_text">I miei ordini</span>
              </a>
            </div>

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

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-gear"></i>
                <span class="link_text">Impostazioni</span>
              </a>
            </div>

            <div class="mob_menu item">
              <a href="#">
                <i class="icn_items fa-regular fa-arrow-right-from-bracket"></i>
                <span class="link_text">Logout</span>
              </a>
            </div>
 
        </div>
    </div>

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

关于javascript - 单击菜单容器外部时如何防止页面滚动和关闭菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72323850/

相关文章:

javascript - 如何居中并使各种图像尺寸适合容器

html - "display=' block '"没有将我的 DIV 保持在同一行

javascript - 如何清除 AngularJs 服务器缓存和 cookie?

javascript - 喝着 Jasmine 来运行我自己的类(class)

css - 具有动态宽度(CSS)的中心固定div

javascript - 如何使用 ReactJs 构建响应式网站

html - 平滑的 CSS "Swinging"悬停时的动画循环

php - 尝试使用 PHP 和 mySQL 创建可编辑的 HTML 表,但该表不会更新

javascript - 移动到最后一里时回到第一里(使用 Jquery 滚动到下一个)

javascript - 如何让JavaScript识别退格键?