纯静态html页面的面包屑必须手写或构建时注入,不可依赖url自动推导;须用包裹,各级用,当前页用,链接用绝对路径,分隔符用css伪元素生成。

纯静态 HTML 页面(比如 index.html)里加面包屑,不能靠 URL 自动推导出语义层级,必须手写结构或借助构建工具注入数据——否则显示的“首页 > 产品 > 小部件”可能和真实信息架构完全对不上。
面包屑必须用 <nav></nav> + <ol></ol> 写,不能用 <div> 或 <code><ul></ul>
搜索引擎和读屏器只认 <nav aria-label="Breadcrumb"></nav> 包裹的 <ol></ol> 结构。用 <div class="breadcrumb"> 看起来一样,但语义丢失,键盘用户 Tab 到这儿时听不到“第1项:首页 → 第2项:产品”,也搜不到结构化路径。
<ul>
<li>
<code><ol></ol> 表达严格顺序,比 <ul></ul> 更准确;序号不显示,但辅助技术会读出层级深度
<li>,上级页用 @#@#@#@#@#@#@#@#@#@0(当前页不该是链接)<nav aria-current="page"><ol>...</ol></nav>(语义错位)<li aria-current="page">HTML 面包屑</li>(无 <a></a>,不可聚焦)/products/),而用户实际在某篇文章里(/products/widget.html),那么 /products/ 仍是可点击的上级,只有文章标题项加 aria-current="page"
分隔符别写死在 HTML 里,用 CSS 伪元素生成
把 > 或 / 直接写进 HTML,读屏器会连读成“首页斜杠产品斜杠当前页”,破坏语义。正确做法是用 ::after 伪元素,并设 aria-hidden="true" 隐藏其可访问性。
- 推荐样式:
ol li:not(:last-child)::after { content: "›"; margin: 0 0.5em; }(›是 U+203A,比>更轻量) - 若需支持 RTL(从右向左语言),在
<nav></nav>上加dir="ltr",防止分隔符被镜像 - 禁用旧式写法:
.breadcrumb-item::before { content: ">" !important; },它和 Bootstrap 5 的--bs-breadcrumb-divider变量冲突 - 不要用背景图或 SVG 作为分隔符——高对比度模式下可能消失,且增加渲染负担
静态站点要不要 JS 动态生成?
除非你用 Vue Router 或 React Router 这类前端路由库,否则在纯 HTML 文件里跑 JS 解析 window.location.pathname 是反模式:它把 /products/widget/index.html 错切成 “Home > products > widget > index”,既不语义也不可靠。
- 5 个以内固定页面,直接手写最稳,改一个链接全站同步
- 用 Hugo/Jekyll:用
{{ .CurrentSection }}或{{ page.url }}注入预置路径数据 - 用 Vite/Webpack:通过
html-webpack-plugin的templateParameters注入结构对象,比如{ breadcrumb: [{ text: "首页", href: "/" }, { text: "文档", href: "/docs/" }] } - 千万别在
index.html里写document.title.split(" | ")[0]当最后一级文本——标题含 SEO 堆砌词,会污染路径语义
最容易被忽略的是:面包屑反映的是用户心智模型里的层级,不是文件系统路径。把 /blog/2024/05/post.html 拆成 “首页 > 博客 > 2024 > 05 > 文章标题”,等于把归档逻辑当成了导航逻辑——这种错位,JS 再怎么解析也救不回来。











