Sass 继承扩展 #
什么是 @extend? #
@extend 指令允许一个选择器继承另一个选择器的样式,实现样式的复用和继承。
scss
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
@extend .message;
border-color: green;
}
.error {
@extend .message;
border-color: red;
}
基本语法 #
scss
.selector1 {
// 基础样式
}
.selector2 {
@extend .selector1;
// 额外样式
}
编译结果 #
基本继承 #
scss
.message {
padding: 10px;
border: 1px solid #ccc;
}
.success {
@extend .message;
border-color: green;
}
// 编译后
.message, .success {
padding: 10px;
border: 1px solid #ccc;
}
.success {
border-color: green;
}
多重继承 #
scss
.message {
padding: 10px;
}
.important {
font-weight: bold;
}
.error {
@extend .message;
@extend .important;
color: red;
}
// 编译后
.message, .error {
padding: 10px;
}
.important, .error {
font-weight: bold;
}
.error {
color: red;
}
链式继承 #
scss
.message {
padding: 10px;
}
.success {
@extend .message;
border-color: green;
}
.success-large {
@extend .success;
font-size: 20px;
}
// 编译后
.message, .success, .success-large {
padding: 10px;
}
.success, .success-large {
border-color: green;
}
.success-large {
font-size: 20px;
}
占位符选择器 #
什么是占位符选择器? #
以 % 开头的选择器称为占位符选择器,它不会单独编译输出,只有被 @extend 继承时才会生成样式。
scss
// 占位符选择器
%button-base {
display: inline-block;
padding: 10px 20px;
border: none;
cursor: pointer;
}
// 不会被编译输出
.button-primary {
@extend %button-base;
background-color: blue;
}
.button-secondary {
@extend %button-base;
background-color: gray;
}
// 编译后
.button-primary, .button-secondary {
display: inline-block;
padding: 10px 20px;
border: none;
cursor: pointer;
}
.button-primary {
background-color: blue;
}
.button-secondary {
background-color: gray;
}
占位符 vs 类选择器 #
scss
// 类选择器:会被编译输出
.button {
padding: 10px;
}
.btn-primary {
@extend .button;
}
// 编译后
.button, .btn-primary {
padding: 10px;
}
// 占位符选择器:不会被编译输出
%button {
padding: 10px;
}
.btn-secondary {
@extend %button;
}
// 编译后(没有 %button)
.btn-secondary {
padding: 10px;
}
@extend vs @mixin #
使用场景对比 #
| 特性 | @extend | @mixin |
|---|---|---|
| 输出方式 | 合并选择器 | 复制样式 |
| 文件大小 | 较小 | 较大 |
| 参数支持 | 不支持 | 支持 |
| 媒体查询 | 有限制 | 无限制 |
| 适用场景 | 相同样式,无参数 | 需要参数或灵活配置 |
@extend 示例 #
scss
%flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.modal {
@extend %flex-center;
}
.overlay {
@extend %flex-center;
}
// 编译后(合并选择器)
.modal, .overlay {
display: flex;
justify-content: center;
align-items: center;
}
@mixin 示例 #
scss
@mixin flex($justify: center, $align: center) {
display: flex;
justify-content: $justify;
align-items: $align;
}
.modal {
@include flex;
}
.overlay {
@include flex(space-between);
}
// 编译后(复制样式)
.modal {
display: flex;
justify-content: center;
align-items: center;
}
.overlay {
display: flex;
justify-content: space-between;
align-items: center;
}
高级用法 #
继承复杂选择器 #
scss
// 继承带伪类的选择器
.link {
color: blue;
&:hover {
text-decoration: underline;
}
}
.button-link {
@extend .link;
background: none;
border: none;
}
// 编译后
.link, .button-link {
color: blue;
}
.link:hover, .button-link:hover {
text-decoration: underline;
}
.button-link {
background: none;
border: none;
}
继承嵌套选择器 #
scss
.container {
.item {
padding: 10px;
}
}
.special-container {
@extend .container;
}
// 编译后
.container .item, .special-container .item {
padding: 10px;
}
使用 !optional #
当继承的选择器不存在时,避免报错:
scss
.element {
@extend .non-existent !optional;
// 不会报错,也不会输出任何内容
}
实际应用示例 #
按钮系统 #
scss
%button-base {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
text-align: center;
text-decoration: none;
transition: all 0.2s ease;
&:hover {
opacity: 0.9;
}
&:active {
opacity: 0.8;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.btn-primary {
@extend %button-base;
background-color: #3498db;
color: white;
}
.btn-secondary {
@extend %button-base;
background-color: #95a5a6;
color: white;
}
.btn-success {
@extend %button-base;
background-color: #2ecc71;
color: white;
}
.btn-danger {
@extend %button-base;
background-color: #e74c3c;
color: white;
}
.btn-outline {
@extend %button-base;
background-color: transparent;
border: 2px solid #3498db;
color: #3498db;
}
表单元素 #
scss
%form-element {
width: 100%;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
transition: border-color 0.2s;
&:focus {
outline: none;
border-color: #3498db;
}
}
.input-text {
@extend %form-element;
}
.input-email {
@extend %form-element;
}
.input-password {
@extend %form-element;
}
.textarea {
@extend %form-element;
min-height: 100px;
resize: vertical;
}
.select {
@extend %form-element;
appearance: none;
background-image: url("data:image/svg+xml,...");
background-repeat: no-repeat;
background-position: right 10px center;
}
消息提示 #
scss
%alert-base {
padding: 15px 20px;
border-radius: 4px;
margin-bottom: 15px;
&::before {
content: "";
margin-right: 10px;
}
}
.alert-success {
@extend %alert-base;
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-danger {
@extend %alert-base;
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-warning {
@extend %alert-base;
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
}
.alert-info {
@extend %alert-base;
background-color: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
卡片组件 #
scss
%card-base {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card {
@extend %card-base;
&__header {
padding: 20px;
border-bottom: 1px solid #eee;
}
&__body {
padding: 20px;
}
&__footer {
padding: 15px 20px;
background-color: #f9f9f9;
}
}
.card-compact {
@extend %card-base;
.card__header {
padding: 10px 15px;
}
.card__body {
padding: 15px;
}
}
@extend 的限制 #
媒体查询限制 #
scss
// 错误:不能跨媒体查询继承
.container {
width: 100%;
}
@media (min-width: 768px) {
.container {
@extend .container; // 错误!
}
}
// 正确:使用 @mixin
@mixin container-width {
width: 100%;
}
.container {
@include container-width;
}
@media (min-width: 768px) {
.container {
@include container-width;
}
}
循环继承 #
scss
// 错误:循环继承
.a {
@extend .b;
}
.b {
@extend .a;
}
最佳实践 #
1. 优先使用占位符选择器 #
scss
// 好:使用占位符
%button-base {
padding: 10px;
}
.btn {
@extend %button-base;
}
// 不好:使用类选择器
.button-base {
padding: 10px;
}
.btn {
@extend .button-base;
}
2. 避免过度继承 #
scss
// 好:适度使用
%base {
padding: 10px;
}
.element {
@extend %base;
}
// 不好:过度继承链
%a { padding: 10px; }
%b { @extend %a; margin: 10px; }
%c { @extend %b; border: 1px; }
%d { @extend %c; color: red; }
3. 配合 @mixin 使用 #
scss
// 基础样式用 @extend
%button-base {
display: inline-block;
cursor: pointer;
}
// 可变样式用 @mixin
@mixin button-color($bg, $color) {
background-color: $bg;
color: $color;
&:hover {
background-color: darken($bg, 10%);
}
}
.btn-primary {
@extend %button-base;
@include button-color(#3498db, white);
}
4. 保持继承关系简单 #
scss
// 好:简单的继承关系
%base { }
.variant-a { @extend %base; }
.variant-b { @extend %base; }
// 不好:复杂的继承网络
%base { }
%variant-a { @extend %base; }
%variant-b { @extend %base; }
%variant-c { @extend %variant-a; }
%variant-d { @extend %variant-b; }
下一步 #
掌握了继承扩展后,继续学习 模块系统,深入了解 @use 和 @forward!
最后更新:2026-03-28