简介:Bootstrap 3 侧边导航栏资源包,面向需要快速搭建响应式侧边栏导航的前端开发初学者与页面重构人员。以可直接运行的 HTML 示例为入口,配合 Bootstrap 3 核心样式、jQuery 与 Bootstrap 脚本,解决了侧边导航在桌面与移动端之间的折叠展开问题,适用于后台管理界面、文档站点及资讯类门户的导航设计。压缩包共 9 个文件,主要包括 HTML 页面、CSS 样式表、JS 脚本及字体图标文件(woff/eot/ttf/svg 等),整体仅 170KB,轻量易用。已有 5178 人学习下载。通过该资源可以直观了解 Bootstrap 3 导航栏的 HTML 结构、navbar-collapse 响应式折叠原理、图标字体的本地引用方式,以及移动端三横线按钮的触发机制;参考示例还能快速定制自己的后台侧边导航,替换链接、增加图标或子菜单,并基于 Bootstrap 的 JavaScript 插件扩展滚动监听等交互,适合作为前端练习和项目起步的轻量参照。
1. Bootstrap 3 侧边导航栏:还在维护老系统的人,最该把这个布局做稳
Bootstrap 3 的侧边导航栏,是我这几年被问得最多的老前端方案之一。不少系统到今天还在跑 Bootstrap 3——内部管理系统、数据分析平台、旧版 CMS 后台,侧边导航是这类页面的标配布局。它由三件事拼成:栅格分栏留出左侧 25% 宽度,Affix 插件让菜单滚到顶时固定住,ScrollSpy 在滚动中自动高亮当前章节,三者配合就是一个完整的侧边导航体验。网上现成示例大多是新版框架的写法,直接抄到 3 上会翻车:Bootstrap 4/5 用 position-sticky,栅格断点不同,Affix 更是 3 的独有插件。这篇笔记写给还要维护老系统、想把侧边导航做稳的开发者,从原理讲到参数,再到五个典型踩坑。
2. 栅格、Affix 与 ScrollSpy:侧边导航栏的三个技术支柱
动手写代码之前,得先把三个插件的职责分清楚:栅格管占位,Affix 管固定,ScrollSpy 管高亮。很多人一上来就复制菜单代码,结果发现固定了不高亮、高亮了不固定,就是因为没搞明白这三件事分别由谁负责。下面逐个拆开讲,每一节都会给出选型理由和边界条件。
2.1 栅格决定占位:col-md-3 的分栏宽度,以及为什么不建议写死像素
Bootstrap 3 的栅格是 12 等分。侧边导航的标准分法是左侧 col-md-3 占 25%,右侧 col-md-9 占 75%。这个比例不是随便选的:导航项文字一般不超过八个字,220 像素左右的内容宽度足够放下常见字号;内容区留 75%,在 14 英寸笔记本上依然能正常呈现表格和多列文本。
栅格断点决定了侧边栏什么时候从「侧边」变成「堆叠」,写代码前最好把这张表背下来:
| 视口范围 | 容器宽度 | col-md-3 实际宽度 | 说明 |
|---|---|---|---|
| 小于 768px(xs) | 自适应 | 100% | 列堆叠,侧边栏跑到正文上方 |
| 768px 及以上(sm) | 750px | 100% | 仍堆叠,需要手动处理 |
| 992px 及以上(md) | 970px | 250px(含 padding,内容 220px) | 侧边栏生效 |
| 1200px 及以上(lg) | 1170px | 300px(含 padding,内容 270px) | 侧边栏生效 |
这里有个容易忽略的点:栅格只管宽度,不管高度。列的实际高度由内容撑起,所以左侧列通常只有菜单那么高。如果想让左侧整条有背景色或边框一直延伸到页面底部,常见做法是给 col-md-3 加 min-height: 100vh,或者用伪元素在视觉上补一条背景。不要用 position: absolute 去拉满高度,那会改变 Affix 计算起始位置的参照点,后患很多。
为什么不建议用固定像素宽度?写死 260px 在 992px 视口下没问题,但到 1200px 以上容器会空出一截,小屏上则会溢出。栅格类自带响应式宽度,改动成本最低,而且后续要给 Affix 算固定宽度时,栅格宽度是可预测的,写死像素则每台设备都不一样。
2.2 Affix 决定固定:状态机与两个偏移参数
Affix 是 Bootstrap 3 独有的滚动定位插件,4/5 里没有,要用得拿 position: sticky 或自写滚动判断。它的行为是一个三态状态机:页面还没滚到设定位置时,元素保持文档流里的原始位置,这个状态叫 affix-top;滚过><!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>BS3 侧边导航示例</title> <link rel="stylesheet" href="css/bootstrap.min.css"> <style> body { position: relative; } #sidebarNav.affix { top: 20px; } </style> </head> <body>#sidebarNav.affix { top: 40px; } @media (min-width: 992px) and (max-width: 1199px) { #sidebarNav.affix { width: 220px; } } @media (min-width: 1200px) { #sidebarNav.affix { width: 270px; } }
这两组宽度不是拍脑袋写的:Bootstrap 3 默认容器在 992px 断点是 970px,加上 row 的负外边距展开为 1000px,col-md-3 占 25% 是 250px,去掉左右各 15px 的列内边距,内容区就是 220px;1200px 断点容器是 1170px,展开 1200px,25% 是 300px,去掉内边距就是 270px。如果项目改了容器宽度,这个值要在控制台里实测,公式是:$('#sidebarNav').parent().width(),在固定前后各取一次,固定后取到的就是需要写进 CSS 的值。
如果嫌媒体查询麻烦,或者容器宽度经常变,可以用事件监听的方式动态赋值:
var $sidebar = $('#sidebarNav'); var $col = $sidebar.parent(); $sidebar.on('affix.bs.affix', function () { $sidebar.css('width', $col.width()); }); $sidebar.on('affix-top.bs.affix affix-bottom.bs.affix', function () { $sidebar.css('width', ''); });当 Affix 从 affix-top 切入 affix 状态时,把父列当前的内容宽度读出来写到固定元素上;退出固定时清掉内联宽度。这个方案的优点是容器宽度改了不用动 CSS,缺点是在状态切换的瞬间可能会有一帧宽度跳动,因为事件触发时 class 已经切过去了。对视觉敏感的项目,建议还是用媒体查询写死,JS 方案只作为非标容器的兜底。
4.3 锚点跳转的偏移修正:平滑滚动与 scroll-margin-top
菜单能固定、能高亮之后,还差最后一截:点击菜单项跳转到对应区块时,区块标题会被固定顶栏遮住。浏览器默认的锚点跳转会把目标元素顶部对齐到视口顶部,固定顶栏一压,标题就没了。现代浏览器的解决方式是 CSS 的 scroll-margin-top:
section[id] { scroll-margin-top: 60px; }section[id] 会把所有带 id 的区块都纳入定位,目标元素的上缘会停在距视口顶部 60px 处,正好让固定顶栏让开。一行解决,不需要任何 JS,而且 ScrollSpy 的判定不受影响。
如果你的项目还需要平滑滚动动画,Bootstrap 3 本身不提供,常见做法是用 jQuery 拦截点击并手动滚动:
$('#sidebarNav').on('click', 'a[href^="#"]:not([data-toggle="collapse"])', function (e) { e.preventDefault(); var $target = $($(this).attr('href')); if ($target.length) { var top = $target.offset().top - 60; $('html, body').animate({ scrollTop: top }, 300); } });选择器里特意排除了带><li> <a href="#subUser">$('#sidebarNav [data-toggle="collapse"]').on('click', function (e) { e.preventDefault(); });
阻止的是锚点跳转,data-target 指定的折叠展开由 Bootstrap 事件接管,不受影响。ScrollSpy 激活二级菜单项时,父级菜单不会自动展开,需要监听 activate 事件手动处理:
$('body').on('activate.bs.scrollspy', function () { var $active = $('#sidebarNav li.active'); $active.closest('.collapse').each(function () { $(this).collapse('show'); $(this).parent('li').addClass('active'); }); });这段在子菜单被高亮时把父级折叠面板展开,同时给父 li 补上 active 类,视觉上才能呈现「父菜单展开、子菜单高亮」的完整状态。
6.2 移动端把侧边栏收进折叠面板
移动端不是简单把菜单藏起来,而是给一个展开入口:
<button class="btn btn-default visible-xs visible-sm" >@media (min-width: 992px) { #sidebarNav.collapse { display: block; } }#sidebarNav 在 HTML 里加 collapse 类,桌面端靠这条媒体查询覆盖成 display: block,小屏端由按钮切换折叠。Affix 的初始化也要跟着改成按宽度决定,把 HTML 里的>if (window.innerWidth >= 992) { $('#sidebarNav').affix({ offset: { top: 70 } }); }
window.innerWidth 在页面加载时读一次即可。这样小屏设备完全不初始化 Affix,避免固定定位在窄视口下遮住内容。
6.3 两分钟验证脚本
交付前我会在控制台跑下面这段,确认插件初始化和状态机完整:
$(function () { console.log('scrollspy:', $('body').data('bs.scrollspy') ? '已初始化' : '未初始化'); console.log('affix:', $('#sidebarNav').data('bs.affix') ? '已初始化' : '未初始化'); $(window).on('scroll resize', function () { var cls = $('#sidebarNav').attr('class') || ''; var state = (cls.match(/affix(-\w+)?/) || ['无'])[0]; console.log('scrollTop:', $(window).scrollTop(), '| 状态:', state); }); });data('bs.scrollspy') 和 data('bs.affix') 只要不是 undefined,说明插件已经初始化;滚动监听会打印出 affix-top、affix、affix-bottom 三种状态的切换节点。验收标准:滚动完整一页,控制台能依次看到三个状态,页脚露出时侧边栏让位,菜单高亮跟随滚动实时切换。
我现在的习惯是侧边导航一上页面,先开控制台跑一遍这段确认状态机完整,再做视觉微调。这个习惯省掉了不少「明明没问题但用户说卡」的沟通成本。多级菜单和移动端折叠都是很小的增量,真正值钱的是把固定、高亮、偏移三个参数当成一个整体来调,而不是各调各的。希望帮到你。
本文还有配套的精品资源,点击获取