面包屑块名必须为 breadcrumb,子元素严格派生;分隔符用 :not(:last-child)::after 实现;当前页用 breadcrumb__text 而非 breadcrumb__link--current;折叠用 breadcrumb__item--collapsed 修饰符并由 JS 控制。

面包屑的块名必须是 breadcrumb,不能加前缀或后缀
很多团队写成 nav__breadcrumb 或 header__breadcrumb,这直接违反 BEM 的块独立性原则。breadcrumb 是一个完整、可复用的导航组件,它在侧边栏、弹窗、详情页都可能出现,不该被父容器“收编”。一旦命名绑定到 nav 或 header,就无法抽离复用,后续改版时连样式文件都得重命名。
正确做法是统一用 breadcrumb 作为 Block 名,所有子元素严格从它派生:
-
breadcrumb__list:包裹整个路径的无序列表() -
breadcrumb__item:每个路径节点的 -
breadcrumb__link:非当前页的可点击链接 -
breadcrumb__text:当前页的纯文本(禁用状态,不可点击) -
breadcrumb__separator:分隔符(不单独写标签,用伪元素实现)
breadcrumb__separator 必须用 :not(:last-child)::after 实现
写 是常见错误。它污染 DOM、增加无障碍负担、且破坏语义——分隔符不是内容,而是视觉装饰。
正确方式是在 breadcrumb__item 上用伪元素生成:
.breadcrumb__item:not(:last-child)::after {
content: "/";
margin: 0 0.5em;
color: #999;
}
这样做的好处:
- DOM 干净,屏幕阅读器不会读出“斜杠”
- 修改分隔符(如换成箭头 → 或 SVG)只需改 CSS,不碰 HTML
- 自动跳过最后一项,无需 JS 控制类名
- 支持 RTL 布局时,
::after会自然跟随文字方向
当前页不能用 breadcrumb__link--current 这类修饰符
把当前页也写成 breadcrumb__link breadcrumb__link--current 看似省事,实则埋雷。因为 breadcrumb__link 隐含“可交互”语义,而当前页是只读文本,两者行为、焦点管理、键盘导航逻辑完全不同。
应该用语义明确的独立元素:
- 非当前页:
用户管理 - 当前页:
这样做能清晰区分:
- 无障碍属性:可给
breadcrumb__text加aria-current="page" - 样式隔离:hover/focus 样式不会误作用于当前页
- JS 控制:切换路径时,只需替换
breadcrumb__link和breadcrumb__text的位置,不涉及状态类切换
折叠/响应式场景下用 breadcrumb__item--collapsed 而不是隐藏元素
移动端常需折叠中间路径(如 “首页 / 产品 / … / 详情”),有人直接 display: none 中间项,结果导致 :not(:last-child)::after 失效——伪元素还在,但被隐藏的项仍参与选择器计算,分隔符错位。
正确做法是加修饰符控制可见性与语义:
- 保留 DOM 结构,仅视觉折叠:
breadcrumb__item--collapsed - 该修饰符应同时处理:
visibility: hidden+position: absolute+width: 0,确保不占位也不影响伪元素逻辑 - 用
aria-hidden="true"明确告知辅助技术该项已折叠
最易忽略的一点:折叠逻辑必须由 JS 控制类名,而不是靠媒体查询自动隐藏。因为折叠阈值(比如最多显示 3 项)往往依赖容器宽度或路径长度,纯 CSS 无法可靠判断。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











