breadcrumb 必须严格使用 breadcrumb__element--modifier 命名,块名是语义锚点;当前页应为 breadcrumb__item--current 作用于 li,分隔符用 li:not(:last-child)::before 控制,中间项需保留 dom 仅隐藏。

必须用 breadcrumb 作为块名起点,所有类名严格遵循 block__element--modifier 结构,否则 BEM 失效、样式不可维护。
为什么 breadcrumb__item 不能写成 crumb-item 或 nav__item
BEM 的块名(block)是语义锚点,所有子元素必须显式归属该块。写成 crumb-item 就脱离了上下文,后续加 breadcrumb--dark 时无法通过层叠影响它;写成 nav__item 更危险——nav 是通用语义块,和其他导航组件冲突,CSS 选择器会误命中。BEM 不是“起个好听的名字”,而是“声明作用域”。
常见错误:
- 用
crumb-item省事,结果在全局 CSS 里加了.crumb-item { margin: 0 },导致侧边栏菜单也塌了间距 - 把当前页写成
breadcrumb__link--current,但 HTML 里当前页根本没有<a></a>,类名和 DOM 结构对不上,hover 样式永远不生效
breadcrumb__item--current 必须作用于 <li>,不是 <a></a>
当前页节点不应该是可跳转链接,这是语义硬约束。屏幕阅读器遇到 aria-current="page" 才会读作“当前位置:详情页”,而不是“链接:详情页”。如果把修饰符错挂到 <a></a> 上,会导致两个问题:
- CSS 中
.breadcrumb__item--current a选中失败(因为里面根本没<a></a>) - 开发者误以为能复用
.breadcrumb__link:hover,结果当前页文字颜色和链接一样,用户分不清哪是活链接
正确结构示例:
不要试图用 .breadcrumb__link--disabled 模拟当前页——disabled 是表单控件状态,不适用于导航语义。
分隔符必须用 li:not(:last-child)::before,不能靠 content: "/\00a0" 硬塞
content: "/\00a0" 里的 \00a0 是不间断空格,它属于文本内容,会被复制粘贴、被屏幕阅读器朗读为“斜杠 空格”,干扰辅助访问。而且一旦响应式缩放,这个空格的宽度不受控。
真正可控的做法是:
- 用
li:not(:last-child)::before插入纯符号,如content: ">" - 把间距交给
li的margin-right控制,而非塞在::before里 - 若需图标替代符号,用
content: url(arrow.svg),避免 base64 冗余或字体图标加载失败白屏
错误写法:li::before { content: " > " }(前后空格不可控,末尾多一个)
正确写法:li:not(:last-child)::before { content: ">"; margin-right: 0.5rem; }
响应式下保留首尾+当前页,其他层级可折叠但不能丢语义
小屏设备上,面包屑常缩为 “首页 > … > 当前页”,但省略的中间项仍需保留在 DOM 中,仅用 display: none 隐藏。否则:
- 屏幕阅读器读不出完整路径,只剩“首页 当前页”,丢失上下文
- SEO 爬虫无法解析层级关系,影响结构化数据收录
- JavaScript 动态展开时,得重新生成 HTML,破坏 SSR 一致性
推荐做法是给中间项加 breadcrumb__item--collapsed,CSS 中控制显示/隐藏,同时保持 <ol></ol> 的完整顺序不变。别为了“看起来简洁”而删 DOM 节点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











