Sass嵌套需以组件为边界控制在3层内,结合BEM命名、@use作用域隔离与文件拆分实现真正模块化,避免超4层嵌套导致选择器冗长、权重过高及性能下降。Sass嵌套本身不等于模块化,但它是实现模块化样式布局的关键支撑手段——真正起作用的是嵌套 + 命名规范 + 文件拆分 + 作用域控制的组合。
嵌套反映的是组件内部结构,不是HTML全局DOM树。比如一个 .card 组件,它的 .card__title 和 .card__body 应该在 .card 下嵌套,而不是跟着页面里所有 h2 或 div 走。
常见错误现象:
article .card h2 { ... } 这类强耦合父级选择器,导致样式无法复用到 section .card
.page .main .content .card .header .title),编译后选择器权重爆炸,后期覆盖困难ul li a),一旦HTML换为 nav 就全失效正确做法:
.card)为嵌套根节点&__title、&__body)和修饰符(&--featured)&:hover、&:focus,避免写成 li:hover a
光有嵌套没用,必须配合 @use 隔离作用域,否则变量、mixin 全局污染,一个组件改了会影响另一个。
立即学习“前端免费学习笔记(深入)”;
示例目录结构:
_components/ _card.scss _button.scssstyles.scss
在 _card.scss 中:
@use 'variables' as v;@use 'mixins' as m;.card { border: 1px solid v.$border-color; @include m.responsive-padding; &__title { color: v.$heading-color; } &--compact { padding: v.$spacing-sm; }}
关键点:
@use 不会把 _card.scss 的变量泄露到全局,其他文件要用必须显式 @use
.card__title 的 CSS 规则只出现在 .card 模块内,不会意外影响其他 h2
最常踩的坑是忘记用 &,导致生成后代选择器而非自身伪类。
错误写法:
.btn { background: blue; :hover { color: white; } // 编译成 .btn :hover → 匹配.btn内所有hover元素}
正确写法:
&:hover → 编译为 .btn:hover
&.is-active → 编译为 .btn.is-active
.btn-group & → 编译为 .btn-group .btn(用于外部上下文覆盖)注意:& 必须紧贴选择器,不能有空格;多个 & 可以连用,但极少需要。
每层嵌套都会增加选择器长度和匹配开销。Sass 不压缩选择器,.layout .sidebar .nav .item .link:hover 这种输出不仅难维护,浏览器渲染时也会更慢。
实测影响:
建议方案:
.component → &__element → &:hover)@extend 替代重复样式,但仅用于语义一致的类(如 .btn 和 .btn-primary)data-state="loading")优先用属性选择器 [data-state="loading"],不靠嵌套推导真正难的不是写嵌套,而是判断哪一层该停——停在组件边界,而不是DOM深度。一旦开始为“这个 div 里面还要再包一层 span”写嵌套,就该拆文件了。