在Sass中使用@include和@extend的区别?

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

2
include并不会让你扩展基类,它只是添加选项。建议您阅读http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#including_a_mixin和http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend。 - CodeGroover
1
另外,@CodeGroover,你的评论毫无用处,也许你误解了问题。阅读此链接可获得更有用的信息:https://gist.github.com/antsa/970172 - temporary_user_name
4
如果你使用一个没有参数的mixin,使用extend会更有效率。 - Abhijeet
5个回答

94

继承不允许自定义,但它们产生非常高效的CSS。

%button
  background-color: lightgrey
  &:hover, &:active
    background-color: white

a
  @extend %button

button
  @extend %button

结果:

a, button {
  background-color: lightgrey;
}
a:hover, button:hover, a:active, button:active {
  background-color: white;
}

使用混合器时,您会获得重复的CSS,但是您可以使用参数来修改每个用法的结果。

=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)

结果为:

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;
}
请按照以下这一系列的代码示例,了解如何通过有效使用继承和混合(mixins)使您的代码更加干净、易于维护:http://thecodingdesigner.com/posts/balancing
请注意,遗憾的是SASS不允许在媒体查询内使用extends(上面链接中相应的示例是错误的)。如果需要基于媒体查询进行扩展,请使用mixin:
=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

结果:

#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比mixin更紧凑,但是当CSS被gzip压缩时,这个优势会减弱。如果您的服务器提供了gzip压缩的CSS(它确实应该!),那么扩展几乎没有任何好处。因此,您可以始终使用mixin!有关此内容的更多信息,请参见:http://www.sitepoint.com/sass-extend-nobody-told-you/


2
我不认为那完全准确...你可以通过覆盖扩展父级来自定义@extends。当然,你不能传递参数,但这是唯一的区别吗?如果是这样,那么@extend只是没有参数的@mixin吗?我仍然看不到优势或差异。 - temporary_user_name
2
以下是一些其他的小问题... https://dev59.com/YF0a5IYBdhLWcg3wD1Lb#30744854 - Toni Leigh
@AndreyMikhaylov-lolmaus 特别关注标记,好像用户阅读它是一个红鲱鱼。用户可能会注意到页面在他们释放鼠标按钮的那一刻被加载。生成您不需要的HTML(请注意,这里有cinje_flush_first,TTFB)可能会影响用户体验。此外,类似于制表符与基于空格的缩进,还会增加碳足迹。 - amcgregor
@AndreyMikhaylov-lolmaus 我最新的应用程序部署具有0.5毫秒(±0.3毫秒)的页面生成时间。 我真的不是在开玩笑,页面在用户完成点击之前就已经加载完毕了。 你们都提到了薪水,我要指出销售额 - amcgregor
@amcgregor 这里有两个要点。第一:您是否测量了从extends到mixins的切换对加载时间的实际影响?第二:您是否测量了您的业务将因此而损失多少钱?还有一个额外的问题:您的业务必须赚取多少收入才值得讨论这个问题?亚马逊是独特的:他们依靠数十亿的小销售,而大多数其他企业则依靠更少的销售。寻找独特产品的客户也有非常不同的习惯:如果我真的需要某些东西,我会购买它,无论等待时间多长。 - Andrey Mikhaylov - lolmaus
显示剩余13条评论

19

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

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

@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);
}

这样可以避免反复调用my-button mixin。这也意味着您不必记住常见按钮的设置,但仍然可以选择创建超级独特的一次性按钮。

我从不久前写的博客文章中引用了这个例子。希望这有所帮助。


16

我认为继承是纯恶,应该避免使用。原因如下:

给定以下 SCSS 代码:

%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:

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

当浏览器不能理解选择器时,它会使整行选择器无效。这意味着您珍贵的mystyle-class在许多浏览器中不再是蓝色的。 这到底意味着什么?如果您随时使用扩展,在可能无法理解选择器的情况下,每个其他使用扩展都将无效。 此行为还允许恶意嵌套:

%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;}

结果:

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

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

Tl;dr: 只要您不使用任何特定于浏览器的选择器,@extend 就完全没问题。如果使用了,则会突然破坏您在任何使用它的地方定义的样式。尽量依赖 mixin 代替!


4
有趣的注释 - simhumileco

4
如果需要传递参数,并且编译输出将根据您传递的内容而改变,请使用mixin。
@include opacity(0.1);

对于任何静态可重复使用的样式块,请使用extend(带有占位符)。

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

0

我完全同意d4nyll之前的回答。有一个关于扩展选项的文本,当我在研究这个主题时,我发现了很多关于扩展的投诉,所以请记住这一点,如果有可能使用mixin代替extend,就跳过extend。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接