如何用jQuery实现绝对定位sub-navbar始终位于navbar下方且不使用position:fixed
现有代码问题
- 条件分支的样式恢复逻辑缺失:滚动高度小于50px的else分支中,没有将navbar的position改回默认值,也没有还原body的marginTop,滚动回顶部时页面布局会错乱
- sub-navbar的top值使用相对运算(
+=5/-=5):scroll事件触发频率极高,每次触发都会叠加修改top值,最终会导致sub-navbar的位置完全偏离预期 - 缺少定位上下文:absolute定位的元素默认相对于根元素定位,未给父容器设置position:relative的前提下,sub-navbar无法和navbar的位置保持联动
- 导航栏布局缺失宽度定义:导航切换定位后,inline-block属性会让它仅适配内容宽度,无法撑满横向视口
可行实现方案
优先推荐纯CSS sticky方案,完全规避fixed的兼容性问题,也没有JS滚动监听的性能开销,目前移动端兼容覆盖率达98%以上,符合绝大多数业务场景需求。
方案1:纯CSS sticky实现(无JS,性能最优)
CSS代码
* { margin: 0; padding: 0; box-sizing: border-box; } body{ height:1500px; } nav{ background :#333; color:#FFF; padding:20px; position: sticky; top: 0; z-index:9999; } .sub-navbar{ background:#CCC; padding:20px; position: sticky; top: 60px; /* 取值等于navbar的总高度 */ z-index: 9998; } p { padding: 15px; }
原有HTML代码无需修改,直接删除原有JS逻辑即可生效。
方案2:兼容极低版本的JS修正方案
如果业务场景需要覆盖极老旧的移动设备,sticky兼容不达标,可以用以下修正后的JS方案,完全规避fixed的布局跳动问题:
HTML代码(新增父容器作为定位上下文)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="nav-wrapper"> <nav id="navbar"> <a>Home</a> <a>About</a> <a>SSQ</a> <a>Contact</a> </nav> <br> <div class="sub-navbar">Sub Navbar</div> </div> <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum,Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat harum ex dolor saepe culpa repellat velit facilis vel itaque labore. </p> <br> <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum,Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat harum ex dolor saepe culpa repellat velit facilis vel itaque labore.
CSS代码
* { margin: 0; padding: 0; box-sizing: border-box; } body{ height:1500px; } .nav-wrapper { position: relative; min-height: 120px; /* 取值等于两个导航的总高度,避免定位切换时页面跳动 */ } nav{ background :#333; color:#FFF; padding:20px; width: 100%; z-index:9999; } .sub-navbar{ background:#CCC; padding:20px; width: 100%; } p { padding: 15px; }
JS代码
// 提前缓存DOM和固定高度,避免滚动时重复计算,提升性能 const $navbar = jQuery('#navbar'); const $subNavbar = jQuery('.sub-navbar'); const navbarHeight = $navbar.outerHeight(); jQuery(window).scroll(function () { const currentScroll = $(window).scrollTop(); if (currentScroll > 50) { $navbar.css({position:'sticky', top: 0}); $subNavbar.css({position:'sticky', top: navbarHeight}); } else { // 直接还原默认定位即可,不需要操作top值 $navbar.css({position:'static'}); $subNavbar.css({position:'static'}); } });
内容的提问来源于stack exchange,提问作者JFeel
相关产品推荐
相关产品推荐

