面包屑导航必须用<nav>包裹并设aria-label="Breadcrumb",内部用<ol>结构,当前页用aria-current="page"标注在<li>上,分隔符用CSS伪元素生成,小屏通过CSS隐藏中间层级并保持语义完整。

面包屑导航的 HTML 结构必须用 <nav> 包裹并设置 aria-label
不加语义化包裹或可访问性属性,屏幕阅读器会把面包屑当成普通文本,用户无法感知这是导航路径。必须用 <nav> 元素,并配 aria-label="Breadcrumb"(值可小写,但不能省略)。内部层级用 <ol> 而非 <div> 或 <ul>:顺序和数量有意义,<ol> 天然表达层级递进关系。
常见错误是直接写一串 <span> 拼接箭头,这样既无法键盘导航,也无法被 AT(辅助技术)识别为导航链。正确结构示例如下:
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/"><span class="visually-hidden">Home</span></a></li>
<li><a href="/products">Products</a></li>
<li aria-current="page">Wireless Headphones</li>
</ol>
</nav>
aria-current="page" 必须加在当前页节点上(不是链接,是 <li>),告诉辅助技术“这就是终点”,避免误读为可点击项。
用 CSS 实现分隔符时,优先用伪元素而非硬编码字符
用 <span>></span> 或 > 直接写在 HTML 里,会导致翻译、缩放、高对比度模式下显示异常,也增加维护成本。应该用 ::before 或 ::after 生成分隔符,并通过 content 控制样式。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 分隔符必须加在
<li>后续兄弟元素前(即除第一个<li>外的所有项前),避免首尾多出符号 - 用
display: inline-flex或display: flex配合gap更可控,但需注意 IE 不支持gap,老项目建议用margin-left+:not(:first-child) - 分隔符颜色应与文字同色或略浅,不要用固定灰度值(如
#999),而用currentColor保证主题适配
推荐写法:
nav ol { list-style: none; padding: 0; margin: 0; display: flex; }
nav li { position: relative; }
nav li:not(:first-child)::before {
content: "/";
position: absolute;
left: -0.75em;
color: currentColor;
opacity: 0.7;
}
nav li a, nav li[aria-current] { padding-right: 0.75em; }
响应式断点下隐藏中间层级比强制换行更可靠
小屏设备上强行让所有层级横向排列,必然溢出或折行错乱。与其用 white-space: nowrap + 滚动容器,不如主动控制可见层级数。例如只保留首项、末项和当前项,中间用 … 占位。
实现要点:
- 不能靠 JS 动态删 DOM(影响 SSR 和 SEO),应在服务端或构建时生成精简结构,或用 CSS
display: none配合媒体查询控制 - 用
nav li:nth-child(n+2):not(:last-child)选择中间项,在@media (max-width: 480px)下设display: none - 若需显示省略号,用
nav li:nth-last-child(2)::after { content: "…"; },但要确保它不参与焦点流(加aria-hidden="true")
注意:省略逻辑必须与实际 URL 路径一致,不能为了视觉简洁而破坏语义层级。
当前页节点不加 <a> 标签但保留 <li> 结构
很多开发者给当前页也套个 <a href="#">,再用 JS 阻止跳转——这会让键盘用户按 Enter 键触发无意义行为,且 href="#" 会滚动到页面顶部。正确做法是当前页节点只保留 <li>,内容为纯文本,加 aria-current="page"。
样式上需单独处理:
- 当前页文本默认禁用下划线、hover 变色等交互反馈
- 若需强调当前页,可用
font-weight: bold或轻微背景色,但对比度仍需满足 WCAG 4.5:1 - 不要对
[aria-current="page"]设置cursor: default,因为这不是 bug,而是标准行为;屏幕阅读器已通过属性告知状态,视觉样式只是辅助
容易忽略的是:当面包屑用于 SPA(如 React Router),路由变化后必须同步更新 aria-current 的位置,否则辅助技术会持续读出旧状态。



















