Bootstrap移动端子菜单异常问题排查与修复求助
Bootstrap 移动端下拉菜单异常问题排查与修复
问题描述
我用以下代码实现了Bootstrap导航栏:
<nav class="navbar navbar-expand-lg fixed-top"> <div class="container"> <a class="navbar-brand px-5" href="index.php"> <img src="img/logo.png" width="110" height="70"> </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav"> <li class="nav-item px-4"> <a class="nav-link active text-white" href="index.php">Home</a> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle text-white" href="" id="navbarDropdown1" role="button" data-bs-toggle="dropdown" aria-expanded="false">Categories</a> <ul class="dropdown-menu"> <?php $sql1 = $db->prepare("SELECT * FROM categories WHERE id IN (SELECT parent FROM categories) AND parent = ? AND deleted = ?"); $sql1->bind_param('ii', $var0, $var0); $sql1->execute(); $result1 = $sql1->get_result(); while($row1 = mysqli_fetch_assoc($result1)){ $test = $row1['id']; ?> <li class="nav-item dropend"> <a class="nav-link active dropdown-toggle" href="" id="navbarDropdown1" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?=$row1['category'];?></a> <ul class="dropdown-menu"> <?php $sql2 = $db->prepare("SELECT * FROM categories WHERE parent IN (SELECT id FROM categories) AND parent = ? AND deleted = ?"); $sql2->bind_param('ii', $row1['id'], $var0); $sql2->execute(); $result2 = $sql2->get_result(); while($row2 = mysqli_fetch_assoc($result2)){ ?> <li><a class="dropdown-item" href="category.php?cat=<?=$row2['id'];?>"><?=$row2['category'];?></a></li> <?php } ?> </ul> <?php } $sql3 = $db->prepare("SELECT * FROM categories WHERE id NOT IN (SELECT parent FROM categories) AND parent = ? AND deleted = ?"); $sql3->bind_param('ii', $var0, $var0); $sql3->execute(); $result3 = $sql3->get_result(); while($row3 = mysqli_fetch_assoc($result3)){ ?> <li><a class="nav-link active" href="category.php?cat=<?=$row3['id'];?>"><?=$row3['category'];?></a></li> <?php } ?> </ul> </li> </li> <li class="nav-item px-4"> <a class="nav-link active text-white" href="about.php">About</a> </li> </ul> </div> </div> </nav> <script> document.addEventListener("DOMContentLoaded", function(){ // make it as accordion for smaller screens if (window.innerWidth > 992) { document.querySelectorAll('.navbar .nav-item').forEach(function(everyitem){ everyitem.addEventListener('mouseover', function(e){ let el_link = this.querySelector('a[data-bs-toggle]'); if(el_link != null){ let nextEl = el_link.nextElementSibling; el_link.classList.add('show'); nextEl.classList.add('show'); } }); everyitem.addEventListener('mouseleave', function(e){ let el_link = this.querySelector('a[data-bs-toggle]'); if(el_link != null){ let nextEl = el_link.nextElementSibling; el_link.classList.remove('show'); nextEl.classList.remove('show'); } }) }); } // end if innerWidth }); // DOMContentLoaded end </script>
对应的CSS:
.dropdown:hover > .dropdown-menu, .dropend:hover > .dropdown-menu{ position: block; margin-top: .125em; margin-left: .125em; } @media screen and (min-width:769px){ .dropend:hover > .dropdown-menu{ position: absolute; top: 0; left: 100%; } }
当前遇到的问题:
- 400x652移动端尺寸下,菜单下拉完全无法工作
- 500x589尺寸下,主菜单下拉正常,但点击子菜单时会关闭主菜单而非展开子菜单
- 移除所有CSS后问题仍存在
问题根源
- 重复ID冲突:子菜单的下拉按钮使用了和主菜单相同的
id="navbarDropdown1",Bootstrap下拉组件依赖唯一ID绑定事件,重复ID会导致事件监听逻辑混乱。 - DOM结构错误:代码中存在多余的闭合
</li>标签(主Categories的<li>后多了一个</li>),破坏了列表项的嵌套结构,导致移动端下拉逻辑失效。 - CSS语法错误:原CSS中
position: block是无效属性值,会影响菜单的定位渲染。 - 移动端事件冒泡未处理:子菜单点击事件会向上冒泡触发父菜单的关闭逻辑,导致点击子菜单时主菜单被收起。
修复方案
1. 修正重复ID
将子菜单的下拉按钮ID改为唯一值,利用循环中的分类ID生成:
<a class="nav-link active dropdown-toggle" href="" id="navbarDropdown-<?=$row1['id'];?>" role="button" data-bs-toggle="dropdown" aria-expanded="false"><?=$row1['category'];?></a>
2. 修复DOM结构错误
删除主Categories的<li class="nav-item dropdown">后面多余的</li>标签(代码中位于</ul>和<li class="nav-item px-4">之间的那个闭合标签),确保列表项嵌套正确。
3. 修正CSS语法错误
将position: block改为有效的position: static(移动端下拉菜单默认静态定位即可):
.dropdown:hover > .dropdown-menu, .dropend:hover > .dropdown-menu{ position: static; margin-top: .125em; margin-left: .125em; }
4. 阻止移动端事件冒泡
修改JS代码,添加子菜单点击事件的阻止冒泡逻辑,避免关闭父菜单:
document.addEventListener("DOMContentLoaded", function(){ // 桌面端悬停逻辑保留 if (window.innerWidth > 992) { document.querySelectorAll('.navbar .nav-item').forEach(function(everyitem){ everyitem.addEventListener('mouseover', function(e){ let el_link = this.querySelector('a[data-bs-toggle]'); if(el_link != null){ let nextEl = el_link.nextElementSibling; el_link.classList.add('show'); nextEl.classList.add('show'); } }); everyitem.addEventListener('mouseleave', function(e){ let el_link = this.querySelector('a[data-bs-toggle]'); if(el_link != null){ let nextEl = el_link.nextElementSibling; el_link.classList.remove('show'); nextEl.classList.remove('show'); } }) }); } // 新增:阻止子菜单点击事件冒泡 document.querySelectorAll('.dropdown-menu .dropdown-toggle').forEach(function(toggle){ toggle.addEventListener('click', function(e){ e.stopPropagation(); }); }); });
5. 确认Bootstrap依赖加载
确保页面已正确引入Bootstrap 5所需的Popper.js和Bootstrap JS文件:
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
内容的提问来源于stack exchange,提问作者Black P
相关产品推荐
相关产品推荐

