面包屑导航必须用<nav>包裹<ol>而非<ul>,因<ol>语义表达有序层级路径,屏幕阅读器可读出“第1项、第2项”,而<ul>仅表无序集合,丢失位置感知;<nav aria-label="Breadcrumb">是辅助技术识别导航区域的必要结构。

面包屑导航为什么必须用 <nav> 包裹 <ol> 而不是 <ul>
因为语义化要求:面包屑是有序的层级路径,<ol> 表达“顺序”和“位置”,<ul> 仅表示无序集合。屏幕阅读器会读出“第1项、第2项…”,而 <ul> 会丢失层级感知。W3C 推荐用 <ol>,且必须嵌套在 <nav aria-label="Breadcrumb"> 中才能被辅助技术正确识别。
<li> 里要不要加 <a>?怎么处理当前页
除最后一项外,所有 <li> 必须包含可点击的 <a>;当前页项不能是链接,但也不能丢掉 <li> —— 否则结构断裂、SEO 和无障碍都受损。常见错误是用 <span> 替代 <li>,这会破坏列表语义。
- ✅ 正确:
<li><a href="/home">首页</a></li><li><a href="/blog">博客</a></li><li aria-current="page">技术文章</li> - ❌ 错误:
<li>技术文章</li>(没声明当前页)或<span>技术文章</span>(不是列表项) -
aria-current="page"是关键,它告诉辅助工具“这是当前位置”,比单纯去掉<a>更可靠
分隔符放在哪?CSS 还是 HTML 里加
分隔符(如 / 或 >)必须用 CSS 的 ::after 生成,不能硬写在 HTML 里。否则:① 屏幕阅读器会读出“首页 / 博客 / 技术文章”,干扰导航;② 当前页项后不该出现分隔符,HTML 静态写死无法动态控制;③ 不利于多语言切换(比如中文习惯用“›”而非“/”)。
推荐写法:
立即学习“前端免费学习笔记(深入)”;
nav[aria-label="Breadcrumb"] ol li:not(:last-child)::after {
content: " › ";
margin: 0 0.5em;
}
响应式折叠时,<li> 的隐藏逻辑怎么写才不伤无障碍
直接 display: none 会彻底移除元素,屏幕阅读器也读不到 —— 折叠后用户可能完全不知道自己在哪一级。正确做法是视觉隐藏但保留语义:
- 用
visibility: hidden+position: absolute或clip-path隐藏中间项,但保持 DOM 结构完整 - 更稳妥的是用 JavaScript 动态生成省略号(如
<li aria-hidden="true">…</li>),同时确保aria-current="page"仍在最后一个可见<li>上 - 永远不要用
aria-hidden="true"包裹整个折叠后的列表 —— 那等于对视障用户说“导航不存在”
最易被忽略的点:分隔符的 CSS 在折叠后是否仍触发渲染、当前页的 aria-current 是否随折叠逻辑动态更新 —— 这些细节一错,整个导航就退化成装饰性元素。



















