纯CSS多级面包屑受限于伪元素不可嵌套、IE11渲染异常及display:contents使计数器失效,推荐用border-right或data属性替代content;语义化需用<nav>包裹<ol>结构,SCSS嵌套应≤三层以避免性能问题。

面包屑层级嵌套写法:避免超过三层
SCSS嵌套本身很适合表达面包屑的 DOM 层级(如 <nav> → <ol> → <li> → <a>),但嵌套过深会导致编译出的选择器冗长、难以调试,甚至触发浏览器选择器性能警告。
推荐结构控制在三层以内,例如:
.breadcrumb {
display: flex;
&__list {
display: flex;
list-style: none;
margin: 0;
padding: 0;
&__item {
margin-right: 0.5rem;
&:last-child {
margin-right: 0;
}
&__link {
color: #666;
text-decoration: none;
&:hover {
color: #007bff;
}
}
}
}
}
注意:&__item 是第三层,&__item__link 是第四层 —— 这已越界。应改为 &__item a 或 &__link 平级声明。
用 & 构建复合类名与状态组合
面包屑常需区分“当前页”“分隔符”“可点击项”,靠 & 可干净生成语义化类名,而非依赖 HTML 中堆砌多个 class。
立即学习“前端免费学习笔记(深入)”;
-
&--active编译为.breadcrumb--active,用于包裹整个组件的变体 -
&__item&--current编译为.breadcrumb__item--current,精准控制当前项样式 -
&__separator单独定义分隔符(如/或>),不嵌套在&__item内 —— 否则会强制它成为子元素,破坏语义
错误写法:&__item { &__separator { ... } } → 编译出 .breadcrumb__item__separator,实际 DOM 中它可能是兄弟节点。
分隔符插入方式:伪元素 vs 真实元素
多数项目倾向用伪元素(::before / ::after)渲染分隔符,避免污染语义结构。SCSS 中用 & 配合伪类最稳妥:
.breadcrumb__item:not(:last-child) {
&::after {
content: "/";
margin: 0 0.5rem;
color: #999;
}
}
关键点:
- 必须用
:not(:last-child)排除末尾项,否则最后多一个/ - 不要写成
&__item::after—— 这会编译为.breadcrumb__item::after,但实际需要的是“非末尾的 item”才渲染 - 若用真实
<span class="breadcrumb__separator">/</span>,则直接写&__separator类,不嵌套
响应式断点嵌套:慎用媒体查询嵌套
面包屑在小屏常折叠为下拉或省略中间项,容易想当然地把 @media 套进嵌套块里:
.breadcrumb {
@media (max-width: 768px) {
&__list {
flex-wrap: wrap;
}
}
}
这看似简洁,但问题明显:
- 编译后媒体查询作用域被限制在
.breadcrumb下,无法影响其他相关组件(如触发折叠的按钮) - 多个类似嵌套会让 CSS 文件中媒体查询分散,不利于集中维护
- Dart Sass 旧版本(
更可靠的做法是:提一层写媒体查询,用根选择器组织:
@media (max-width: 768px) {
.breadcrumb__list {
flex-wrap: wrap;
}
.breadcrumb__item:not(:first-child):not(:last-child) {
display: none;
}
}
复杂点在于:面包屑的交互逻辑(如省略号点击展开)往往需要 JS 配合,纯 SCSS 无法处理 DOM 节点动态增删 —— 这部分样式必须预留钩子(如 .breadcrumb__item--collapsed),不能只靠嵌套推导。


















