单击暗区时如何关闭侧面菜单?

时间:2020-01-16 17:11:06

标签: javascript html css

我构建了一个简单的侧面导航。如果您运行该代码段并将窗口调整为较小的尺寸,则会看到一个红色正方形。如果单击它,菜单将打开。

菜单打开正常,但是当我单击暗区而不是X时,我想关闭菜单。我尝试向主体本身添加“ click” eventListener并删除“ is-open”类,但是没用。我花了几个小时思考可能是什么问题,最后决定在这里发帖并征求您的建议。

"use strict";

const menuToggle = document.querySelector(".menu-toggle");
const menuClose = document.querySelector(".menu-close");
const nav = menuToggle.parentElement;

menuToggle.addEventListener("click", event => {
  event.preventDefault();
  nav.classList.add("is-open");
  document.body.style.backgroundColor = "rgba(0,0,0,0.5)";
});

menuClose.addEventListener("click", event => {
  event.preventDefault();
  menuToggle.nextElementSibling.style.width = null;
  document.body.style.backgroundColor = null;
  nav.classList.remove("is-open");
});
:root {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
}

.menu-toggle {
  width: 40px;
  height: 40px;
  border: 1px solid red;
  cursor: pointer;
}

.menu-container {
  position: absolute;
  background: lightskyblue;
  height: 100vh;
  width: 0;
  transition: width 0.4s ease-in-out;
  top: 0;
  left: 0;
  overflow: auto;
  z-index: 1;
}

.menu-close {
  position: absolute;
  right: 1em;
}

.nav-menu {
  list-style: none;
  padding-left: 0;
  margin: 50px 0 0 0;
}

.nav-menu > li + li {
  border-top: 1px solid #fff;
}

.nav-menu > li > a {
  display: block;
  color: #000;
  padding: 0.8em 1em;
  font-size: 1.1rem;
  text-decoration: none;
  text-transform: uppercase;
}


.nav.is-open .menu-container {
  width: 200px;
}

.menu-close::before {
  content: "\00d7";
  font-size: 2.6rem;
}

/*@media screen and (min-width: 37.5em) {*/
@media screen and (min-width: 40.5em) {
  body {
    background: #fff !important;
  }

  .menu-toggle {
    display: none;
  }

  .nav.is-open .menu-container {
    width: auto;
    height: auto;
  }

  .menu-container {
    position: initial;
    height: auto;
    width: auto;
    overflow: hidden;

  }

  .menu-close {
    display: none;
  }

  .nav-menu {
    display: flex;
    position: static;
    justify-content: center;
    margin: 0;
  }

  .nav-menu > li {
    margin-left: 1em;
  }

  .nav-menu > li + li {
    border-top: initial;
  }
}
<!DOCTYPE html>
<html lang="en-US">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="hamburgerside.css">
  <title>Hamburger Menu Side</title>
</head>
<body>
<nav class="nav">
  <div class="menu-toggle">
    <span class="menu-toggle__linecenter"></span>
  </div>

  <div class="menu-container">
    <span class="menu-close"></span>
    <ul class="nav-menu">
      <li><a href="#">Home</a></li>
      <li><a href="#">Menu Item 1</a></li>
      <li><a href="#">Menu Item 2</a></li>
      <li><a href="#">Menu Item 3</a></li>
    </ul>
  </div>
</nav>

<main>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    Accusamus accusantium aliquid consequatur facere illum
    incidunt magnam magni maiores nam neque numquam omnis
    perferendis porro quae quibusdam, quos sed tenetur ullam.
  </p>
</main>
<script src="hamburgerside.js"></script>
</body>
</html>

2 个答案:

答案 0 :(得分:2)

因此,如果我正确理解您要采取的措施,则您需要对点击事件使用open_basedir而不是document。您还需要使用body而不是event.stopImmediatePropagation()来允许第一次单击,但不允许第二次单击。同样,在这种情况下,只要单击菜单之外的任何地方,都只需要运行click事件即可。

注意:我不得不删除您的媒体查询,因为它阻止了切换菜单的显示。

event.preventDefault()
"use strict";

const menuToggle = document.querySelector(".menu-toggle");
const menuClose = document.querySelector(".menu-close");
const nav = menuToggle.parentElement;

menuToggle.addEventListener("click", event => {
  event.stopImmediatePropagation();
  
  nav.classList.add("is-open");
  document.body.style.backgroundColor = "rgba(0,0,0,.5)";
});

document.addEventListener("click", event => {
  if (nav.classList.contains("is-open") && !event.target.classList.contains("nav-menu")) {
    menuToggle.nextElementSibling.style.width = null;
    document.body.style.backgroundColor = "#fff";
    nav.classList.remove("is-open");
  }
});
:root {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
}

.menu-toggle {
  width: 40px;
  height: 40px;
  border: 1px solid red;
  cursor: pointer;
}

.menu-container {
  position: absolute;
  background: lightskyblue;
  height: 100vh;
  width: 0;
  transition: width 0.4s ease-in-out;
  top: 0;
  left: 0;
  overflow: auto;
  z-index: 1;
}

.menu-close {
  position: absolute;
  right: 1em;
}

.nav-menu {
  list-style: none;
  padding-left: 0;
  margin: 50px 0 0 0;
}

.nav-menu > li + li {
  border-top: 1px solid #fff;
}

.nav-menu > li > a {
  display: block;
  color: #000;
  padding: 0.8em 1em;
  font-size: 1.1rem;
  text-decoration: none;
  text-transform: uppercase;
}


.nav.is-open .menu-container {
  width: 200px;
}

.menu-close::before {
  content: "\00d7";
  font-size: 2.6rem;
}

}

答案 1 :(得分:1)

这是您想要的,我在菜单旁边添加了一个带有类hidden的新div,并且对于脚本,当event.target等于该div或关闭按钮时,将触发功能。检查一下,让我知道是否有任何疑问。

const menuToggle = document.querySelector(".menu-toggle");
const menuClose = document.querySelector(".menu-close");
const menuActive = document.querySelector(".menu_active");
const nav = menuToggle.parentElement;

const log = console.log;

const app = {
  init: () => {
    app.menuToggle();
  },

  menuToggle: () => {
    menuToggle.addEventListener("click", event => {
      event.preventDefault();
      nav.classList.add("is-open");
      menuActive.classList.remove('hidden');
      app.closeMenu();
    });
    log('working')

  },
  closeMenu: () => {
    if (nav.classList.contains('is-open')) {

      document.addEventListener("click", event => {
        event.preventDefault();
        let closeMenu = event.target.className;
        if (closeMenu === 'menu_active' || closeMenu === 'menu-close') {
          //log(event.target.className)
          menuToggle.nextElementSibling.style.width = null;
          menuActive.classList.add('hidden');
          nav.classList.remove("is-open");
        }
      });
    }
  }

};


document.addEventListener('DOMContentLoaded', app.init())
:root {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
}

.menu_active {
  background: rgba(0, 0, 0, 0.5);
  position: absolute;
  height: 100vh;
  width: calc(100vw - 200px);
  top: 0;
  right: 0;
}

.hidden {
  visibility: hidden;
  display: none;
}

.menu-toggle {
  width: 40px;
  height: 40px;
  border: 1px solid red;
  cursor: pointer;
}

.menu-container {
  position: absolute;
  background: lightskyblue;
  height: 100vh;
  width: 0;
  transition: width 0.4s ease-in-out;
  top: 0;
  left: 0;
  overflow: auto;
  z-index: 1;
}

.menu-close {
  position: absolute;
  right: 1em;
}

.nav-menu {
  list-style: none;
  padding-left: 0;
  margin: 50px 0 0 0;
}

.nav-menu>li+li {
  border-top: 1px solid #fff;
}

.nav-menu>li>a {
  display: block;
  color: #000;
  padding: 0.8em 1em;
  font-size: 1.1rem;
  text-decoration: none;
  text-transform: uppercase;
}

.nav.is-open .menu-container {
  width: 200px;
}

.menu-close::before {
  content: "\00d7";
  font-size: 2.6rem;
}


/*@media screen and (min-width: 37.5em) {*/

@media screen and (min-width: 40.5em) {
  body {
    background: #fff !important;
  }
  .menu-toggle {
    display: none;
  }
  .nav.is-open .menu-container {
    width: auto;
    height: auto;
  }
  .menu-container {
    position: initial;
    height: auto;
    width: auto;
    overflow: hidden;
  }
  .menu-close {
    display: none;
  }
  .nav-menu {
    display: flex;
    position: static;
    justify-content: center;
    margin: 0;
  }
  .nav-menu>li {
    margin-left: 1em;
  }
  .nav-menu>li+li {
    border-top: initial;
  }
}
<body>
  <nav class="nav">
    <div class="menu-toggle">
      <span class="menu-toggle__linecenter"></span>
    </div>

    <div class="menu-container">
      <span class="menu-close"></span>
      <ul class="nav-menu">
        <li><a href="#">Home</a></li>
        <li><a href="#">Menu Item 1</a></li>
        <li><a href="#">Menu Item 2</a></li>
        <li><a href="#">Menu Item 3</a></li>
      </ul>
    </div>
    <div class="menu_active hidden"></div>
  </nav>

  <main>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus accusantium aliquid consequatur facere illum incidunt magnam magni maiores nam neque numquam omnis perferendis porro quae quibusdam, quos sed tenetur ullam.
    </p>
  </main>
</body>