面包屑必须用包裹结构,当前页用标识,分隔符须由CSS伪元素生成并设aria-hidden="true"。

面包屑必须用 <nav></nav> 包裹并设 aria-label="Breadcrumb"
不加 <nav></nav> 容器,屏幕阅读器会把面包屑当普通文本读,用户完全感知不到这是导航路径;漏掉 aria-label="Breadcrumb",部分读屏工具甚至不归类为“导航”类型。常见错法包括:<div class="breadcrumb"> 替代 <code><nav></nav>、写了 <nav></nav> 却没加 aria-label、或误写成 aria-labelledby(需额外绑定 ID,纯属多此一举)。
静态页和 SPA 都适用这个结构,aria-label 值固定写死即可,无需随路由动态更新。
<ol></ol> 是唯一推荐的内部容器,不是 <ul></ul> 也不是 <div>
<p>面包屑本质是严格顺序的层级路径:首页 → 分类 → 子分类 → 当前页。“先后”是语义本身,不是靠 CSS 视觉流模拟出来的。<code><ol></ol> 会被读屏器正确读出“第 1 项、第 2 项……”,而 <ul></ul> 表示无序集合,直接破坏路径逻辑。Lighthouse 会将 <ul></ul> 写法标红为“语义缺失”。
即使你用 list-style: none 隐藏了数字,<ol></ol> 的语义依然有效——辅助技术仍能识别层级深度。
立即学习“前端免费学习笔记(深入)”;
常见错误:<div> 套文字加斜杠、<code><ul></ul> 包链接、用 innerHTML 拼接字符串生成列表(破坏语义与可访问性)。
当前页必须用 <li aria-current="page"> 标识,且只能加在 <li> 上
这是 JAWS/NVDA/VoiceOver 唯一能正确识别为“当前位置”的方式。写成 class="active"、aria-disabled="true" 或 aria-current="true" 全部无效。
关键细节:
-
aria-current="page"必须加在当前页对应的<li>元素上,不是加在<a></a>、<ol></ol>或<nav></nav>根节点 - 当前页项不应是可点击链接,所以里面不要放
<a></a>;若保留(如某些 CMS 分类页),至少加tabindex="-1"和aria-disabled="true" - 值必须是
"page",大小写敏感,不能是"current"或"location"
分隔符必须用 CSS 伪元素生成,禁用 HTML 硬编码
把 / 或 > 直接写进 HTML,读屏器会连读成“首页斜杠产品斜杠当前页”,破坏语义连贯性。正确做法是用 ::before 或 ::after 生成,并加 aria-hidden="true" 隐藏其可访问性。
推荐写法:
nav ol li:not(:first-child)::before {
content: "›";
margin-left: 0.5em;
aria-hidden: true;
}
注意点:
- 用
›(U+203A)比>更轻量、视觉更协调 - 若需 RTL 支持,在
<nav></nav>上加dir="ltr",防止分隔符被镜像 - 避免使用
!important,它会和 Bootstrap 等框架的--bs-breadcrumb-divider变量冲突
最易被忽略的是:纯静态 HTML 页面无法靠 window.location.pathname 自动推导真实业务层级——URL 路径和信息架构常常不一致。手写结构或构建时注入才是唯一可靠方式。



















