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

如何用JS实现Bootstrap 5下拉菜单:桌面hover展开、移动端点击切换

Bootstrap 5 响应式下拉菜单修复方案

需求与问题

需要实现导航栏下拉菜单的响应式行为:

  • 桌面端:鼠标hover时展开/收起下拉菜单,点击菜单标题跳转至对应页面
  • 移动端:点击菜单标题展开/收起下拉菜单,点击时不跳转页面

当前实现中,桌面端功能正常,但移动端点击菜单标题会直接跳转页面,无法展开下拉菜单。


修改后的完整代码

HTML 代码

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <title>Home | </title>

  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <link rel="stylesheet" href="./css/index.css" />
  <link rel="icon" type="image/x-icon" href="/Bootstrap-/images/favicon-32x32.png">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
  
  <!-- NAVIGATION BAR START -->
  <nav class="navbar navbar-expand-lg navbar-light py-3 sticky-top" id="navbar-color">
    <div class="container">
      <a href="/Bootstrap-/index.html">
        <img src="./src/img/logo-topnav.png" height="45" width="225" class="img-fluid"/>
      </a>

      <!-- TOGGLE MENU START -->
      <button
        type="button"
        class="navbar-toggler"
        data-bs-toggle="collapse"
        data-bs-target="#navmenu"
      >
        <span class="navbar-toggler-icon"></span>
      </button>
      <!-- TOGGLE MENU CLOSE -->

      <div class="collapse navbar-collapse" id="navmenu">
        <ul class="navbar-nav ms-auto">
          <li class="nav-item"><a href="/Bootstrap-/index.html" class="nav-link text-white" id="nav_object">Home</a></li>
          <li class="nav-item"><a href="/Bootstrap-/about.html" class="nav-link text-white" id="nav_object">About</a></li>
          <li class="nav-item dropdown">
            <!-- 添加Bootstrap下拉触发器标识 -->
            <a class="nav-link text-white dropdown-toggle" href="/Bootstrap-/services.html" role="button" data-bs-toggle="dropdown" aria-expanded="false" id="nav_object">
              Services
            </a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item text-capitalize text-white" href="/Bootstrap-/cctv.html">CCTV Services</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/datacenter.html">Datacenter Support</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/digital-signage.html">Digital Signage</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/gen-support.html">General Support</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/net-support.html">Network Support</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/pos.html">POS Services</a></li>
              <li><a class="dropdown-item text-white text-capitalize" href="/Bootstrap-/telecom.html">Telecom Services</a></li>
            </ul>
          </li>
          <li class="nav-item"><a href="/Bootstrap-/contact.html" class="nav-link text-white" id="nav_object">Contact</a></li>
        </ul>
      </div>
    </div>
  </nav>
  <!-- NAVIGATION BAR CLOSE -->

  <!-- 自定义交互逻辑 -->
  <script>
    const dropdownTrigger = document.querySelector('.dropdown-toggle');
    
    dropdownTrigger.addEventListener('click', function(e) {
      // 匹配Bootstrap navbar-expand-lg的断点(992px)
      if (window.innerWidth < 992) {
        e.preventDefault();
        const dropdownMenu = this.nextElementSibling;
        if (dropdownMenu.classList.contains('show')) {
          dropdownMenu.classList.remove('show');
          this.setAttribute('aria-expanded', 'false');
        } else {
          dropdownMenu.classList.add('show');
          this.setAttribute('aria-expanded', 'true');
        }
      }
    });

    // 窗口大小切换时重置下拉状态
    window.addEventListener('resize', function() {
      if (window.innerWidth >= 992) {
        const dropdownMenu = dropdownTrigger.nextElementSibling;
        dropdownMenu.classList.remove('show');
        dropdownTrigger.setAttribute('aria-expanded', 'false');
      }
    });
  </script>
</body>
</html>

CSS 代码(优化后)

#navbar-color {
    background-color: hsl(210, 45%, 30%);
}

.navbar-light .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

.navbar-light .navbar-toggler {
    border: 1px solid hsl(0, 0%, 100%);
    outline: none;
    box-shadow: none;
}

#nav_object {
    position: relative;
}

/* 仅桌面端生效的hover样式 */
@media (min-width: 992px) {
    .dropdown:hover .dropdown-menu {
        display: block;
        background-color: hsl(210, 45%, 30%);
    }

    #nav_object::after {
        content: '';
        opacity: 0;
        transition: all 0.2s;
        height: 2px;
        width: 100%;
        background: hsl(18, 100%, 62%);
        position: absolute;
        bottom: 0;
        left: 0;
    }
    
    #nav_object:hover::after {
        opacity: 1;
    }
}

.dropdown-item:hover {
    background-color: hsl(210, 55%, 41%);
}

.dropdown-menu{
  --bs-dropdown-link-hover-bg: hsl(210, 55%, 41%) !important;
}

修改说明

  1. HTML 修改:为下拉菜单的触发链接添加dropdown-toggle类和data-bs-toggle="dropdown"属性,让Bootstrap识别下拉组件逻辑。
  2. CSS 修改:
    • 将hover展开下拉的样式限定在min-width:992px的媒体查询中,与Bootstrap的桌面端断点保持一致
    • 移除移动端无效的hover触发样式,避免干扰点击交互
  3. JavaScript 修改:
    • 监听下拉触发链接的点击事件,移动端(屏幕宽度<992px)时阻止默认跳转,手动切换下拉菜单的显示状态
    • 监听窗口大小变化,切换到桌面端时自动收起下拉菜单,保持界面状态一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:54:50