在Sass中使用@include vs @extend?

Using @include vs @extend in Sass?

在Sass中,我无法完全分辨使用@include与mixin和使用@extend与占位符类之间的区别。它们不是同一件事吗?


扩展不允许自定义,但它们会生成非常有效的CSS。

1
2
3
4
5
6
7
8
9
10
%button
  background-color: lightgrey
  &:hover, &:active
    background-color: white

a
  @extend %button

button
  @extend %button

结果:

1
2
3
4
5
6
a, button {
  background-color: lightgrey;
}
a:hover, button:hover, a:active, button:active {
  background-color: white;
}

使用mixins,您将获得重复的CSS,但是您可以使用参数来修改每种用法的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
=button($main-color: lightgrey, $active-color: white)
  background-color: $main-color
  border: 1px solid black
  border-radius: 0.2em

  &:hover, &:active
    background-color: $active-color

a
  +button

button
  +button(pink, red)

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a {
  background-color: lightgrey;
  border: 1px solid black;
  border-radius: 0.2em;
}
a:hover, a:active {
  background-color: white;
}

button {
  background-color: pink;
  border: 1px solid black;
  border-radius: 0.2em;
}
button:hover, button:active {
  background-color: red;
}

请遵循以下连续的代码示例集,以了解如何通过有效地使用扩展和混合来使代码更清洁,更可维护:http://thecodingdesigner.com/posts/balancing

请注意,不幸的是,SASS不允许在媒体查询内部使用扩展(并且上述链接中的相应示例是错误的)。在需要基于媒体查询进行扩展的情况下,请使用mixin:

1
2
3
4
5
6
7
8
9
10
11
12
13
=active
  display: block
  background-color: pink

%active
  +active

#main-menu
  @extend %active // Active by default

#secondary-menu
  @media (min-width: 20em)
    +active // Active only on wide screens

结果:

1
2
3
4
5
6
7
8
9
10
11
#main-menu {
  display: block;
  background-color: pink;
}

@media (min-width: 20em) {
  #secondary-menu {
    display: block;
    background-color: pink;
  }
}

在这种情况下,复制是不可避免的,但是您不必太在意它,因为Web服务器的gzip压缩将解决它。

PS请注意,您可以在媒体查询中声明占位符类。

2014-12-28更新:扩展生成的CSS比mixins更紧凑,但是压缩CSS时,这种好处会减弱。如果您的服务器提供压缩的CSS(确实如此!),那么扩展几乎不会给您带来任何好处。因此,您始终可以使用mixins!此处的更多信息:http://www.sitepoint.com/sass-extend-nobody-told-you/


一个好的方法是同时使用两者-创建一个mixin,它将允许您进行大量自定义,然后扩展该mixin的常规配置。例如(SCSS语法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@mixin my-button($size: 15, $color: red) {
  @include inline-block;
  @include border-radius(5px);
  font-size: $size + px;
  background-color: $color;
}
%button {
  @include my-button;
}
%alt-button {
  @include my-button(15, green);
}
%big-button {
  @include my-button(25);
}

这使您不必一遍又一遍地调用"我的按钮" mixin。这也意味着您不必记住常用按钮的设置,但仍可以选择一个超级独特的一次性按钮。

我以不久前写的博客文章为例。希望这会有所帮助。


在我看来,扩展是纯粹的邪恶,应避免。原因如下:

给出了scss:

1
2
3
4
%mystyle {color: blue;}
.mystyle-class {@extend %mystyle}
//basically anything not understood by target browser (such as :last-child in IE8):
::-webkit-input-placeholder {@extend %mystyle}

将生成以下CSS:

1
2
3
.mystyle-class, ::-webkit-input-placeholder { //invalid in non-webkit browsers
  color: blue;
}

当浏览器不了解选择器时,它将使选择器的整行无效。这意味着您宝贵的mystyle-class不再是蓝色的(对于许多浏览器而言)。
这到底是什么意思?如果您在任何时候使用扩展程序而浏览器可能无法理解选择器,则该扩展程序的其他所有使用都会失效。
此行为还允许进行邪恶嵌套:

1
2
3
4
5
%mystyle {color: blue;}
@mixin mystyle-mixin {@extend %mystyle; height: 0;}
::-webkit-input-placeholder {@include mystyle-mixin}
//you thought nesting in a mixin would make it safe?
.mystyle-class {@extend %mystyle;}

结果:

1
2
3
4
5
6
7
::-webkit-input-placeholder, .mystyle-class { //invalid in non-webkit browsers
  color: blue;
}

::-webkit-input-placeholder {
  height: 0;
}

Tl; dr:只要您从未将其与任何浏览器特殊选择器一起使用,@ extend就是可以的。如果这样做,无论您在哪里使用它,它都会突然拆下样式。尝试改用mixins!


如果mixins接受参数,请使用mixins,编译后的输出将根据传递给它的内容而改变。

1
@include opacity(0.1);

对所有静态的可重复样式块使用扩展(带有占位符)。

1
2
3
color: blue;
font-weight: bold;
font-size: 2em;

我完全同意d4nyll的先前回答。有一篇关于扩展选项的文章,当我研究这个主题时,我发现了很多关于扩展的抱怨,因此请记住,如果有可能使用mixin而不是扩展,只需跳过扩展即可。