面包屑必须用<nav>包裹并添加aria-label="Breadcrumb",内部用<ol>按顺序列出带有效href的<a>链接,当前页用aria-current="page"标记,分隔符须用伪元素生成,且SPA中需动态同步更新aria-current状态。

面包屑必须用 <nav> 包裹才符合语义
不加 <nav> 的面包屑,对屏幕阅读器来说只是普通文字,无法被识别为导航结构。很多开发者直接用 <div> 或 <p> 套 <span>,这会让辅助技术忽略它的导航意图。
正确做法是:整个面包屑区域必须包裹在 <nav> 中,并添加 aria-label="Breadcrumb" 显式声明用途:
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li aria-current="page">Wireless Headphones</li>
</ol>
</nav>
-
<ol>比<ul>更合适——路径有明确顺序,序号逻辑天然匹配层级关系 - 当前页用
aria-current="page"标记,而非仅靠 CSS 隐藏链接,这是屏幕阅读器识别“终点”的关键信号 - 避免用
<nav>嵌套多个导航(比如同时放主导航和面包屑),每个<nav>应职责单一
<li> 里不能只放文本,链接必须可聚焦
常见错误是把中间节点写成纯文本(如 <li>Products</li>),既无法键盘访问,也破坏了导航链路完整性。所有非当前页节点都必须是有效 <a> 元素。
注意点:
立即学习“前端免费学习笔记(深入)”;
- 链接
href必须指向真实可访问的 URL,空字符串href="#"或javascript:void(0)会导致键盘用户按 Enter 后页面跳动或无响应 - 如果某级分类暂无列表页(比如“分类A”还没建站),宁可先做占位链接并加
aria-disabled="true",也不要删掉<a> - 不要给
<a>加tabindex="-1"——这会主动剥夺键盘焦点能力
CSS 样式不影响语义,但会影响焦点流和视觉层次
用 /、> 或图标分隔面包屑时,这些符号必须放在 <li> 外部或用伪元素生成,绝不能塞进 <a> 或 <li> 内容里干扰 DOM 结构。
推荐写法:
ol.breadcrumb { display: flex; list-style: none; padding: 0; }
ol.breadcrumb li:not(:last-child)::after {
content: ">";
margin: 0 0.5em;
color: #999;
}
- 用
::before/::after插入分隔符,确保 DOM 中只有干净的<li>和<a> - 当前页项(
aria-current="page")建议用font-weight: bold或不同颜色,但不要移除其作为<li>的角色 - 响应式断行时,避免用
white-space: nowrap强制单行——长路径在小屏上会溢出或遮挡内容
动态生成时,aria-current 必须随路由实时更新
单页应用(SPA)里,面包屑常由 JS 动态渲染。如果只靠初始 HTML 渲染,切换路由后 aria-current="page" 不更新,屏幕阅读器仍会读出旧的“当前页”。
关键动作:
- 每次路由变化后,重新遍历
<ol>下的<li>,清除所有aria-current,再给匹配当前路径的项加上aria-current="page" - 不要依赖 CSS 类名(如
.is-active)来判断——辅助技术不认这个 - 若用 React/Vue,确保该属性是响应式绑定,而非仅在组件挂载时设一次
语义不是加个标签就完事,它活在 DOM 状态与用户操作的同步里。漏掉一次 aria-current 更新,对视障用户就是一次迷路。



















