Bootstrap offcanvas菜单关闭后页面自动回顶问题求助
解决Bootstrap Offcanvas关闭后页面自动返回顶部的问题
问题描述
使用Bootstrap的Offcanvas侧边栏时,点击菜单内的锚点链接(如#contacts)可正常滚动到页面对应位置,但关闭Offcanvas后页面会自动返回顶部,尝试的两段JavaScript代码均无效。
错误原因分析
- 事件名错误:第一段代码使用了错误的事件名
hidden.bs.offcanvasMenu,正确的Offcanvas隐藏事件名应为hidden.bs.offcanvas。 - 滚动位置时机错误:第一段代码在页面加载时就记录
scrollY,而非点击锚点后滚动到目标位置的实际滚动值。 - 元素选择错误:第二段代码选择的元素ID是
offcanvasNav,但实际Offcanvas的ID是offcanvasMenu,导致事件监听无效。 - 触发按钮的href冲突:触发Offcanvas的按钮使用
href="#offcanvasMenu",关闭菜单后焦点默认返回该按钮,浏览器会尝试滚动到#offcanvasMenu元素(该元素为fixed定位,实际在视口外),最终导致页面回到顶部。
解决方案
步骤1:修正触发按钮的HTML
将触发按钮的href替换为data-bs-target,避免hash变化引发的滚动问题:
<a class="bi bi-list offcanvas-icon" data-bs-toggle="offcanvas" data-bs-target="#offcanvasMenu" role="button" aria-controls="offcanvasMenu"></a>
步骤2:添加正确的JavaScript代码
以下代码会记录点击锚点后的滚动位置,并在Offcanvas关闭后恢复该位置:
// 获取Offcanvas元素 const offcanvas = document.getElementById('offcanvasMenu'); // 存储滚动位置的变量 let scrollPosition = 0; // 监听菜单内的锚点点击事件,记录滚动后的位置 document.querySelectorAll('#offcanvasMenu a[href^="#"]').forEach(link => { link.addEventListener('click', () => { // 延迟获取滚动位置,确保页面已完成滚动 setTimeout(() => { scrollPosition = window.scrollY; }, 100); // 手动关闭Offcanvas bootstrap.Offcanvas.getInstance(offcanvas).hide(); }); }); // 监听Offcanvas完全隐藏的事件,恢复滚动位置 offcanvas.addEventListener('hidden.bs.offcanvas', () => { window.scrollTo({ top: scrollPosition, behavior: 'smooth' // 可选:添加平滑滚动效果 }); });
备选方案(通过配置禁用焦点返回)
如果不需要Offcanvas关闭后返回焦点到触发按钮,可通过初始化配置解决:
// 初始化Offcanvas并禁用焦点返回 const offcanvasElement = document.getElementById('offcanvasMenu'); const offcanvas = new bootstrap.Offcanvas(offcanvasElement, { focus: false }); // 处理锚点点击的滚动和菜单关闭 document.querySelectorAll('#offcanvasMenu a[href^="#"]').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetId = link.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) { // 滚动到目标位置 targetElement.scrollIntoView({ behavior: 'smooth' }); // 关闭菜单 offcanvas.hide(); } }); });
内容的提问来源于stack exchange,提问作者Vladislav Kolesnik
相关产品推荐
相关产品推荐

