面包屑导航必须是一个独立Block,命名为breadcrumb,其下元素breadcrumb__list、breadcrumb__item、breadcrumb__link、breadcrumb__text、breadcrumb__separator均为直接子元素,禁止嵌套命名;分隔符须用:not(:last-child)::after伪元素实现;当前页必须用breadcrumb__text替代breadcrumb__link以保持语义与DOM层级一致。

面包屑导航必须是一个 Block,不是多个
整个面包屑区域(从首页到当前页)是一个语义完整、可复用、职责独立的 UI 单元,对应唯一 Block 名 breadcrumb。它不是由 nav、ol、li 这些 HTML 标签拆出来的多个 Block,也不是把“首页”“商品”“详情页”各自当成独立 Block —— 那会破坏导航的上下文关系和状态同步能力。
常见错误是写成:.nav__breadcrumb 或 .page-header__breadcrumb,这等于把 breadcrumb 当作某个父容器的子元素来命名,结果导致:
- 换个页面位置(比如从顶部移到侧边栏),类名就得改,复用性归零
- 主题切换时,
nav--dark无法自然影响breadcrumb样式,得额外加覆盖规则 - JS 控制“当前页高亮”或“折叠逻辑”时,要跨 Block 查询,代码变脆
breadcrumb 下的元素只能是一级,不能嵌套
breadcrumb__list、breadcrumb__item、breadcrumb__link、breadcrumb__text、breadcrumb__separator 全部是 breadcrumb 的直接子元素(语义上),不允许出现 breadcrumb__item__link 或 breadcrumb__link__icon 这类二级 Element。
原因很实际:
立即学习“前端免费学习笔记(深入)”;
-
breadcrumb__item__link看似结构清晰,但一旦link要在其他地方复用(比如用户列表的操作列),它就不再是“仅属于 breadcrumb 的子部件”,而是该升格为独立 Blockaction-link - BEM 的作用域隔离靠的是命名前缀 + 语义边界,嵌套 Element 会让 CSS 选择器隐含层级依赖,比如
.breadcrumb__item .breadcrumb__link实际等价于后代选择器,容易被意外覆盖 - 当前页用
breadcrumb__text替代breadcrumb__link,正是为了保持 DOM 层级一致 —— 它们同属breadcrumb__item的直接子节点,CSS 可以统一控制间距、对齐、换行等
分隔符(separator)必须是 breadcrumb 的 Element,不能独立成 Block
breadcrumb__separator 不是功能组件,而是面包屑内部视觉节奏的一部分,它的样式(颜色、间距、图标)强依赖 breadcrumb 的状态(如 breadcrumb--dark)和尺寸(如 breadcrumb--compact)。抽成独立 Block 会导致:
- 重复定义主题变量或手动传参,维护成本翻倍
- 响应式下动态增删 item 时,
separator的显示/隐藏逻辑分散在 JS 和 CSS 两处,容易错位 - 辅助技术误读:如果用
<span class="separator">/</span>,屏幕阅读器会把它当作普通文本朗读;而用breadrumb__item:not(:last-child)::after,它只是装饰性伪元素,不参与语义流
实操中直接用伪元素最稳:.breadcrumb__item:not(:last-child)::after { content: ">"; },不用 HTML 内联字符,也不用 SVG 标签 —— 后者需显式设宽高,且 fallback 成本高。
当前页(current)状态不能挂 link 上,也不能用 modifier 模拟
当前页不是“禁用的链接”,而是“非导航文本”。所以不能写 breadcrumb__link--current 或 breadcrumb__link--disabled,更不能只加 aria-current="page" 就完事。
正确做法只有两种之一:
- DOM 层级替换:当前页节点用
<span class="breadcrumb__text">详情页</span>,而非<a class="breadcrumb__link"> - 类名标记:当前页的
li加breadcrumb__item--current,同时内部仍用breadcrumb__text(保持结构一致性)
这样做的硬性收益是:焦点顺序不乱、hover/focus 样式只作用于可跳转项、CSS 可以精准写 .breadcrumb__link:hover 而不污染当前页文本、服务端渲染或 SSR 时语义不会漂移。
最容易被忽略的一点:BEM 类名里出现的下划线数量,必须和语义层级严格对应。比如 breadrumb__item 只能出现在 breadrumb 的直接子节点上,哪怕 HTML 里它嵌在 <ol> 里,也不能因此写成 breadrumb__list__item —— 因为 list 不是 Block,它只是 breadrumb 的实现细节。


















