再次单击时如何关闭手风琴菜单

时间:2019-04-15 14:44:44

标签: css

我仅基于HTML和CSS构建了一个简单的手风琴菜单。功能不错,但是问题是当您单击打开的手风琴时,它不会关闭。

我可以使用CSS还是需要JavaScript?

.middle a {
  text-decoration: none;
}

.menu {
  width: 100%;
  overflow: hidden;
}

.item {
  border-top: 1px solid #2980b9;
  overflow: hidden;
}

.btn {
  display: block;
  padding: 16px 20px;
  background: #3498db;
  color: white;
  position: relative;
}

.btn:before {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  background: #3498db;
  left: 20px;
  bottom: -7px;
  transform: rotate(45deg)
}

a i {
  margin-right: 10px;
  margin-left: 10px
}

.smenu {
  background: white;
  overflow: hidden;
  transition: max-height 0.3s;
  max-height: 0;
}

.smenu a {
  display: block;
  padding: 16px 26px;
  font-size: 14px;
  margin: 4px 0;
  position: relative;
}

.smenu a:before {
  content: "";
  position: absolute;
  width: 6px;
  height: 100%;
  background: #3498db;
  left: 0;
  top: 0;
  transition: 0.3s;
  opacity: 0;
}

a:hover:before {
  opacity: 1;
}

.item:target .smenu {
  max-height: 100%;
}

.item {
  list-style-type: none
}
<div class="middle">
  <div class="menu">
    <li class="item" id="aboutus">
      <a href="#aboutus" class="btn">About Us</a>
      <div class="smenu">
        <a href="#">1</a>
        <a href="#">2</a>
        <a href="#">3</a>
        <a href="#">4</a>
        <a href="#">5</a>
        <a href="#">6</a>
      </div>
    </li>
    <li class="item" id="contactus">
      <a href="#contactus" class="btn">Contact Us</a>
      <div class="smenu">
        <a><i class="fas fa-phone"></i>000-000-000</a>
        <a><i class="fas fa-envelope-open"></i>Send Us An Email</a>
        <a>ABCDEFG</a>
        <a>P.O> Box 00000</a>
        <a>New York, New York 000000</a>
        <a><i class="fas fa-clock"></i>Monday - Friday: 9AM - 5PM ET</a>
        <a><i class="fas fa-window-close"></i>Saturday-Sunday: Closed</a>
        <a><i class="fas fa-desktop"></i>Online: 24/7</a>
      </div>
    </li>
    <li class="item" id="sitelinks">
      <a href="#sitelinks" class="btn">Site Links</a>
      <div class="smenu">
        <a href="#">1</a>
        <a href="#">2</a>
        <a href="#">3</a>
        <a href="#">4t</a>
        <a href="#">5</a>
        <a href="#">6</a>
      </div>
    </li>


  </div>
</div>

1 个答案:

答案 0 :(得分:1)

问题

打开一个手风琴面板是基于该面板li class="item"是当前的 target (哈希)

.item:target .smenu {
  max-height: 100%;
}

那么,关闭该面板的唯一方法是使<li>不再是目标,再次单击该项目将不会执行该操作。您将不得不单击其他内容,或者使用javascript-因此“我可以使用CSS还是需要JavaScript?” 的基本答案是您需要javascript。 >

JavaScript做到了

好消息是这是一个非常简单的javascript。在这里,将它包装在DOMContentLoaded中,如果它位于从页面链接的自己的.js文件中,则需要这样做:

document.addEventListener("DOMContentLoaded", function(event) {
    const items = document.querySelectorAll('.menu li.item');
    for (let item of items) {
        item.addEventListener('click', function(e) {
                if ('#'+e.currentTarget.id === location.hash) {
                    e.preventDefault();
                    window.location.hash = '';
                }
        });
    }
});

它有什么作用?

此查询(querySelectorAll)所有菜单项; li.item内的.menu个 然后,它循环遍历每个事件,并为“ click”事件附加事件侦听器。就是这样。

事件监听器本身也很简单。如果事件e与当前位置相同,它将使用事件id并获取当前点击目标的.item:target。哈希表示您正在单击已打开的内容。 ..阻止默认操作(再次导航到哈希),然后清除哈希。

现在清除了哈希后,const items = document.querySelectorAll('.menu li.item'); for (let item of items) { item.addEventListener('click', function(e) { if ('#'+e.currentTarget.id === location.hash) { e.preventDefault(); window.location.hash = ''; } }); } CSS选择器不匹配任何内容,因此关闭了先前打开的手风琴窗格。

作为堆栈片段

制作代码片段时,该代码片段负责等待DOM准备就绪,因此我们将关闭该包装器。在这里,我要做的就是在自己的代码段中添加一些Javascript:

.middle a {
  text-decoration: none;
}

.menu {
  width: 100%;
  overflow: hidden;
}

.item {
  border-top: 1px solid #2980b9;
  overflow: hidden;
}

.btn {
  display: block;
  padding: 16px 20px;
  background: #3498db;
  color: white;
  position: relative;
}

.btn:before {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  background: #3498db;
  left: 20px;
  bottom: -7px;
  transform: rotate(45deg)
}

a i {
  margin-right: 10px;
  margin-left: 10px
}

.smenu {
  background: white;
  overflow: hidden;
  transition: max-height 0.3s;
  max-height: 0;
}

.smenu a {
  display: block;
  padding: 16px 26px;
  font-size: 14px;
  margin: 4px 0;
  position: relative;
}

.smenu a:before {
  content: "";
  position: absolute;
  width: 6px;
  height: 100%;
  background: #3498db;
  left: 0;
  top: 0;
  transition: 0.3s;
  opacity: 0;
}

a:hover:before {
  opacity: 1;
}

.item:target .smenu {
  max-height: 100%;
}

.item {
  list-style-type: none
}
<div class="middle">
  <div class="menu">
    <li class="item" id="aboutus">
      <a href="#aboutus" class="btn">About Us</a>
      <div class="smenu">
        <a href="#">1</a>
        <a href="#">2</a>
        <a href="#">3</a>
        <a href="#">4</a>
        <a href="#">5</a>
        <a href="#">6</a>
      </div>
    </li>
    <li class="item" id="contactus">
      <a href="#contactus" class="btn">Contact Us</a>
      <div class="smenu">
        <a><i class="fas fa-phone"></i>000-000-000</a>
        <a><i class="fas fa-envelope-open"></i>Send Us An Email</a>
        <a>ABCDEFG</a>
        <a>P.O> Box 00000</a>
        <a>New York, New York 000000</a>
        <a><i class="fas fa-clock"></i>Monday - Friday: 9AM - 5PM ET</a>
        <a><i class="fas fa-window-close"></i>Saturday-Sunday: Closed</a>
        <a><i class="fas fa-desktop"></i>Online: 24/7</a>
      </div>
    </li>
    <li class="item" id="sitelinks">
      <a href="#sitelinks" class="btn">Site Links</a>
      <div class="smenu">
        <a href="#">1</a>
        <a href="#">2</a>
        <a href="#">3</a>
        <a href="#">4t</a>
        <a href="#">5</a>
        <a href="#">6</a>
      </div>
    </li>


  </div>
</div>
items

最后,由于除了循环之外,您不需要document.addEventListener("DOMContentLoaded", function(event) { document.querySelectorAll('.menu li.item') .forEach(element => element.addEventListener('click', e => { if ('#'+e.currentTarget.id === location.hash) { e.preventDefault(); window.location.hash = ''; } }) ) }); ,因此您甚至不必将它们分配给变量。
这是进一步的最小化版本,用箭头函数替换了显式函数。

if ('#'+e.currentTarget.id === ...

{{1}}也可能会变成谓词,但我将其留给读者练习。