面包屑导航本质是语义化链接链路,须用包裹,每级为真实可访问链接,当前页用aria-current="page"标识,禁用#或相对路径,动态路由需通过matched或usematches安全提取层级。

面包屑导航的本质是语义化链接链路,不是视觉组件
它不是靠 CSS 画出来的“箭头分隔条”,而是用 <nav></nav> 包裹、<ol></ol> 或 <ul></ul> 列出的层级化链接。搜索引擎和屏幕阅读器依赖这个结构识别页面位置。如果只用 <div> 拼接文字加斜杠,等于扔掉了语义价值。
<p>常见错误现象:<code>TypeError: Cannot read property 'pathname' of undefined(在前端路由中没取到当前路径)、点击后跳转 404(链接写死或未适配 base 路径)、移动端折叠后无法操作(没加 aria-current="page")。
- 必须用
<nav aria-label="Breadcrumb"></nav>开头,明确导航类型 - 推荐用
<ol></ol>(有序列表),因为路径有严格层级顺序 - 当前页用
<li aria-current="page">首页</li>,不要用class="active"替代 - 每级链接的
href必须是真实可访问路径,不能是#或空字符串
静态网站直接写 HTML,别用 JS 动态生成
如果你的网站没有前端路由(比如纯 HTML 文件 + Apache/Nginx),就老老实实手写。动态生成反而增加首屏阻塞、SSR 不友好、SEO 抓取失败风险。
示例(/products/shoes/sneakers.html 页面):
<nav aria-label="Breadcrumb"><ol>
<li><a href="/index.html">首页</a></li>
<li><a href="/products/index.html">商品</a></li>
<li><a href="/products/shoes/index.html">鞋类</a></li>
<li aria-current="page">运动鞋</li>
</ol></nav>
- 路径全部用绝对路径(以
/开头),避免相对路径在子目录下错乱 - 每个中间页都应存在对应 HTML 文件,否则链接失效
- 不要把“首页”写成
href="#",这会让键盘用户无法跳转,也破坏历史记录
Vue Router / React Router 中怎么安全生成
关键不是“怎么渲染”,而是“怎么提取层级”。不能靠 location.pathname.split('/') 硬切,会漏掉动态段(如 /user/:id)或带查询参数的路径。
- Vue Router:用
useRoute().matched,遍历matched数组里的meta.title和path - React Router v6:用
useMatches(),它返回匹配的路由对象数组,含id、pathname、handle(可放自定义 title) - 所有动态参数必须在路由定义时通过
meta或handle预置真实标题,不能 runtime 解析:id - 注意嵌套路由中
index路由的处理——它没有 pathname,但可能需要显示为“列表”或“概览”
CSS 样式只需最小干预,重点在可访问性
视觉上加斜杠、箭头、背景色都是次要的。真正影响体验的是焦点管理、颜色对比度、触控区域大小。
- 用
::before或::after插入分隔符(如content: "/";),别用图片或额外标签 - 确保
aria-current="page"元素有明显视觉区分(比如字体加粗 + 灰色文本),且颜色对比度 ≥ 4.5:1 - 移动端给
<a></a>设置min-height: 44px,防止误触 - 不要隐藏
<ol></ol>的默认序号(list-style: none是必须的),但别连counter-reset都删了——它会影响屏幕阅读器读序号
http://localhost:3000)上线后全挂掉。上线前务必逐个点开检查 HTTP 状态码。











