使用mmenuJS插件时固定滚动头部出现异常问题
问题原因及解决方案
核心原因
高度计算时机错误:你在
DOMContentLoaded触发时先获取了.header__top的高度headerFixedPosition,随后才初始化mmenu。但mmenu初始化过程中会修改DOM结构(比如移动菜单元素、添加offcanvas容器),导致页面布局发生变化,初始获取的header高度和实际渲染后的高度不符,滚动时的判断条件window.scrollY > headerFixedPosition无法满足,因此不会添加fixed类。堆叠上下文冲突:mmenu的offcanvas模式会给页面内容容器添加
transform属性(如translate3d),这会创建新的堆叠上下文,导致设置了position: fixed的header不再相对于视口定位,而是相对于这个带transform的容器,滚动时无法固定显示。而打开关闭菜单后,mmenu会移除或调整该transform属性,fixed定位恢复正常。
解决方案
方案1:延迟计算header高度
将header高度的计算移到mmenu初始化完成之后,确保获取的是布局稳定后的高度:
window.addEventListener('DOMContentLoaded', () => { // 先初始化mmenu const menu = new Mmenu("#mobilemenu", { offCanvas: { position: 'right' }, slidingSubmenus: false }); const api = menu.API; document.querySelector("#openmenu").addEventListener("click", () => { api.open(); }); // 初始化完成后再计算header高度 const headerFixedPosition = document.querySelector('.header__top').clientHeight; window.addEventListener('scroll', () => { if (window.scrollY > headerFixedPosition) { document.querySelector('.header__top').classList.add('fixed'); document.body.style.paddingTop = `${headerFixedPosition}px`; if (window.scrollY > (headerFixedPosition + 50)) { document.querySelector('.header__top').classList.add('fade-in') } else { document.querySelector('.header__top').classList.remove('fade-in') } } else { document.querySelector('.header__top').classList.remove('fixed') document.body.style.paddingTop = 0; } }); })
方案2:禁用mmenu的页面transform
修改mmenu配置,关闭页面容器的transform属性,避免创建堆叠上下文影响fixed定位:
const menu = new Mmenu("#mobilemenu", { offCanvas: { position: 'right', page: { css: { transform: false } } }, slidingSubmenus: false });
方案3:滚动时动态计算高度
将header高度的计算移到scroll事件内部,每次滚动都重新获取最新高度,避免布局变化导致的数值过时:
window.addEventListener('scroll', () => { const headerFixedPosition = document.querySelector('.header__top').clientHeight; if (window.scrollY > headerFixedPosition) { document.querySelector('.header__top').classList.add('fixed'); document.body.style.paddingTop = `${headerFixedPosition}px`; if (window.scrollY > (headerFixedPosition + 50)) { document.querySelector('.header__top').classList.add('fade-in') } else { document.querySelector('.header__top').classList.remove('fade-in') } } else { document.querySelector('.header__top').classList.remove('fixed') document.body.style.paddingTop = 0; } });
内容的提问来源于stack exchange,提问作者pkberlin
相关产品推荐
相关产品推荐

