You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:多Dropdown菜单点击时全部展开,如何实现单次仅展开一个?

解决下拉菜单点击全部展开的问题

问题说明

实现点击触发的下拉菜单,默认隐藏内容,点击按钮显示。但点击单个菜单按钮时所有菜单同时展开,希望每次仅展开一个;同时疑问:JS中用到的show类未在HTML预先添加却能运行,是否需要添加?

原代码

HTML

<div class="hidden">
  <button id="myFunction()" class="dropbtn">Title of Section</button>
  <div id="myDropdown" class="hidden-content">
    <div class="article-list"></div>
  </div>
</div>

注:存在多个上述结构,所有下拉容器的ID均为myDropdown

CSS

.dropbtn {
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
  width: 100%;
  font-family: 'Turret Road';
  font-size: 35px;
  font-weight: 600;
  color: var(--default5);
  text-align: center;
  border-radius: 15px;
  background-image: linear-gradient(var(--defaultAccent1), var(--default3Muted));
  box-shadow: var(--default1) 3px 3px 3px 3px;
}

.dropbtn:hover, .dropbtn:focus {
  background-image: linear-gradient(var(--defaultAccent1), var(--default1));
}

.hidden {
  position: relative;
  display: inline-block;
}

.hidden a:hover {
  background-image: linear-gradient(var(--defaultAccent1), var(--default1));
}

.hidden-content {
  display: none;
  position: relative;
  right: 0;
  width: 100%;
  background-color: var(--default3Muted);
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
  border-radius: 15px;
}

.show {
  display: block;
}

.hidden-content a {
  color: var(--default1);
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

JS

function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    var dropdowns = document.getElementsByClassName("hidden-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}

错误原因

  1. ID重复违规:HTML中ID必须唯一,所有下拉容器用同一个myDropdown ID,导致JS无法精准定位单个菜单。
  2. 按钮事件绑定错误:按钮的id被错误设置为myFunction(),正确的事件绑定应该使用onclick属性调用函数,而非将ID设为函数名。
  3. 函数无法关联当前菜单:原myFunction直接操作固定ID的元素,无法区分点击的按钮所属的下拉容器。

关于show类的疑问

不需要预先在HTML中添加show类。classList.toggle()方法会动态为元素添加/移除该类,只要CSS中定义了.show的样式,动态添加后就能立即生效,完全没问题。

修改后的代码

HTML

<!-- 第一个下拉菜单 -->
<div class="dropdown-container">
  <button onclick="toggleDropdown(this)" class="dropbtn">Title of Section 1</button>
  <div class="hidden-content">
    <div class="article-list">
      <a href="#">选项1</a>
      <a href="#">选项2</a>
    </div>
  </div>
</div>

<!-- 第二个下拉菜单 -->
<div class="dropdown-container">
  <button onclick="toggleDropdown(this)" class="dropbtn">Title of Section 2</button>
  <div class="hidden-content">
    <div class="article-list">
      <a href="#">选项A</a>
      <a href="#">选项B</a>
    </div>
  </div>
</div>

用dropdown-container替换原hidden类(更语义化),按钮通过onclick="toggleDropdown(this)"传递自身元素给函数,无需重复ID

CSS

仅修改容器类名,其余样式保留:

.dropbtn {
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
  width: 100%;
  font-family: 'Turret Road';
  font-size: 35px;
  font-weight: 600;
  color: var(--default5);
  text-align: center;
  border-radius: 15px;
  background-image: linear-gradient(var(--defaultAccent1), var(--default3Muted));
  box-shadow: var(--default1) 3px 3px 3px 3px;
}

.dropbtn:hover, .dropbtn:focus {
  background-image: linear-gradient(var(--defaultAccent1), var(--default1));
}

/* 替换原.hidden类 */
.dropdown-container {
  position: relative;
  display: inline-block;
}

.dropdown-container a:hover {
  background-image: linear-gradient(var(--defaultAccent1), var(--default1));
}

.hidden-content {
  display: none;
  position: relative;
  right: 0;
  width: 100%;
  background-color: var(--default3Muted);
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
  border-radius: 15px;
}

.show {
  display: block;
}

.hidden-content a {
  color: var(--default1);
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

JS

function toggleDropdown(btn) {
  // 关闭所有其他已展开的下拉菜单
  const allOpenDropdowns = document.querySelectorAll('.hidden-content.show');
  allOpenDropdowns.forEach(dropdown => {
    if (dropdown !== btn.nextElementSibling) {
      dropdown.classList.remove('show');
    }
  });
  // 切换当前点击的下拉菜单的显示状态
  btn.nextElementSibling.classList.toggle('show');
}

window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    const dropdowns = document.getElementsByClassName('hidden-content');
    for (let i = 0; i < dropdowns.length; i++) {
      const openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}

函数接收点击的按钮元素,通过nextElementSibling找到对应的下拉容器,先关闭其他展开的菜单,再切换当前菜单的状态


内容的提问来源于stack exchange,提问作者sunnybirdboi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 05:25:55