**SCSS 嵌套:**SCSS 允许你将 CSS 选择器像 HTML 结构一样嵌套书写,使样式代码的结构与 DOM 结构保持一致,提高可读性和可维护性。
为什么需要SCSS嵌套
假设你要写一个用户信息卡片,HTML 结构如下(这是典型的组件结构):
<div class="user-card">
<div class="avatar">
<img src="user.jpg" alt="头像">
</div>
<div class="info">
<h3 class="name">张三</h3>
<p class="role">前端工程师</p>
<div class="actions">
<button class="btn btn-message">发消息</button>
<button class="btn btn-follow">关注</button>
</div>
</div>
</div>
方式一:纯原生 CSS(无嵌套)
/* styles.css */
.user-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
display: flex;
gap: 12px;
}
.user-card .avatar img {
width: 60px;
height: 60px;
border-radius: 50%;
}
.user-card .info {
flex: 1;
}
.user-card .info .name {
margin: 0 0 4px 0;
font-size: 18px;
color: #333;
}
.user-card .info .role {
margin: 0 0 10px 0;
color: #777;
font-size: 14px;
}
.user-card .info .actions {
display: flex;
gap: 8px;
}
.user-card .info .actions .btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.user-card .info .actions .btn-message {
background: #007AFF;
color: white;
}
.user-card .info .actions .btn-follow {
background: #eee;
color: #333;
}
方式二:SCSS 嵌套
// user-card.scss(完全不用 &)
.user-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
display: flex;
gap: 12px;
.avatar {
img {
width: 60px;
height: 60px;
border-radius: 50%;
}
}
.info {
flex: 1;
.name {
margin: 0 0 4px 0;
font-size: 18px;
color: #333;
}
.role {
margin: 0 0 10px 0;
color: #777;
font-size: 14px;
}
.actions {
display: flex;
gap: 8px;
.message-btn {
padding: 6px 12px;
background: #007AFF;
color: white;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.follow-btn {
padding: 6px 12px;
background: #eee;
color: #333;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
}
}
}
SCSS 嵌套的优势
| 优势 | 说明 |
|---|---|
| 1. 结构对齐 HTML | SCSS 的缩进层级 = HTML 的嵌套层级,一眼看懂“谁是谁的孩子” |
| 2. 减少重复 | 不用手写 .user-card .info .actions .xxx 每次都从头开始 |
| 3. 易于维护 | 要修改 .info 相关样式?直接找到 .info { ... } 块即可 |
| 4. 安全作用域 | 所有样式都限定在 .user-card 内,不会意外影响其他组件 |
| 5. 重构方便 | 如果要把 .user-card 改名为 .member-card,只需改一行 |
如何把SCSS 嵌套转换成原生 CSS
SCSS 的嵌套 不是 CSS 属性的继承(inheritance),而是 选择器的自动拼接(selector concatenation)。
关于选择器的内容,请参考:HTML、CSS和JS的入门:选择器(Selectors)
SCSS 代码(使用嵌套):
.btn-group {
display: flex;
gap: 8px;
.btn {
padding: 6px 12px;
border: 1px solid #ccc;
background: white;
.icon {
margin-right: 4px;
}
}
}
拼接规则(核心逻辑):每进入一层嵌套,就把外层的选择器 + 空格 + 当前选择器,作为新的完整选择器。
| SCSS 嵌套层级 | 拼接过程 | 最终 CSS 选择器 |
|---|---|---|
.btn-group |
最外层,直接使用 | .btn-group |
.btn(在 .btn-group 内) |
.btn-group + 空格 + .btn |
.btn-group .btn |
.icon(在 .btn 内,而 .btn 在 .btn-group 内) |
.btn-group + 空格 + .btn + 空格 + .icon |
.btn-group .btn .icon |
编译后的原生 CSS:
.btn-group {
display: flex;
gap: 8px;
}
.btn-group .btn {
padding: 6px 12px;
border: 1px solid #ccc;
background: white;
}
.btn-group .btn .icon {
margin-right: 4px;
}
.btn-group .btn {...}:“选中所有 class 为 btn 的元素,但前提是:这个 btn 必须位于某个 class 为 btn-group 的元素内部(可以是直接子元素,也可以是更深层的后代)。”
.btn-group .btn 被称为 后代选择器(descendant selector)