Usando @include vs @extend no Sass?

92

No Sass, não consigo discernir a diferença entre usar @includecom um mixin e usar @extendcom uma classe de espaço reservado. Eles não significam a mesma coisa?

Temporary_user_name
fonte
2
include não dá a você estender a classe base, apenas adiciona opções. Apenas aconselho você a ler sass-lang.com/docs/yardoc/… e sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend
CodeGroover
1
Além disso, @CodeGroover, não é um comentário útil, talvez você tenha entendido mal a pergunta. Lendo isso dá mais informações úteis: gist.github.com/antsa/970172
temporary_user_name
4
Sempre que você usar um mixin sem nenhum parâmetro, um extend será mais eficiente. Cortesia Chris
Abhijeet

Respostas:

86

As extensões não permitem personalização, mas produzem CSS muito eficiente.

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

a
  @extend %button

button
  @extend %button

Resultado:

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

Com mixins, você obtém CSS duplicado, mas pode usar argumentos para modificar o resultado de cada uso.

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

Resulta em:

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

Siga este conjunto consecutivo de exemplos de código para ver como você pode tornar seu código mais limpo e mais fácil de manter usando extensões e mixins de forma eficaz: http://thecodingdesigner.com/posts/balancing

Observe que o SASS infelizmente não permite o uso de extensões dentro de consultas de mídia (e o exemplo correspondente do link acima está errado). Na situação em que você precisa estender com base em consultas de mídia, use um 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

Resultado:

#main-menu {
  display: block;
  background-color: pink;
}

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

A duplicação é inevitável neste caso, mas você não deve se preocupar muito com isso, porque a compressão gzip do servidor da web cuidará disso.

PS Observe que você pode declarar classes de espaço reservado nas consultas de mídia.

Atualização 2014-12-28 : Extensões produzem CSS mais compacto do que os mixins , mas esse benefício é diminuído quando o CSS é compactado com gzip. Se o seu servidor serve CSS compactado (realmente deveria!), O extends não oferece quase nenhum benefício. Então você sempre pode usar mixins ! Mais sobre isso aqui: http://www.sitepoint.com/sass-extend-nobody-told-you/

Andrey Mikhaylov - lolmaus
fonte
2
Eu não acho que isso não seja totalmente preciso ... você pode personalizar @extendssubstituindo o pai da extensão. Claro que você não pode passar argumentos, mas essa é a única diferença? Nesse caso, fica @extendapenas @mixinsem argumentos? Ainda não vejo vantagem ou diferença.
Temporary_user_name
2
Aqui estão algumas outras peculiaridades ... stackoverflow.com/questions/30744625/…
Toni Leigh
Eu seria cuidadoso ao interpretar o aspecto "não oferece quase nenhum benefício" do último parágrafo. A compactação Gzip é um codificador Huffman baseado em dicionário, portanto, se a repetição ocorrer longe o suficiente, o texto não estará presente no dicionário e as taxas de compactação serão afetadas. Eu ainda prefiro sempre @extendque possível, pois isso irá produzir CSS mais compacto, que ainda irá comprimir muito bem (é texto ASCII, depois de tudo).
amcgregor
@amcgregor, a diferença é insignificante.
Andrey Mikhaylov - lolmaus
@ AndreyMikhaylov-lolmaus eu concordo! Eu esperaria que a diferença fosse essencialmente imensurável durante a transmissão, independentemente da escolha para qualquer coisa até um megabyte ou mais de CSS gerado, exceto o fato de que o resultado final descompactado na memória será mais compacto usando @extend. Esta é uma micro-otimização aparentemente baseada na intuição e sentimentos viscerais, ao invés de uma compreensão de como o esquema de compressão envolvido realmente funciona. (Além disso: ele ignora a sobrecarga considerável da codificação de transferência gzip sob demanda; a compactação não é gratuita
!;
18

Uma boa abordagem é usar os dois - criar um mixin que permitirá muitas personalizações e, então, fazer extensões para configurações comuns desse mixin. Por exemplo (sintaxe 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);
}

Isso evita que você chame o mixin my-button repetidamente. Isso também significa que você não precisa se lembrar das configurações dos botões comuns, mas ainda pode criar um botão super único e único, se assim desejar.

Pego esse exemplo de uma postagem no blog que escrevi não muito tempo atrás. Espero que isto ajude.

FreddyBushBoy
fonte
12

Na minha opinião, extensões são pura maldade e devem ser evitadas. Aqui está o porquê:

dado o 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}

O seguinte css será gerado:

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

Quando um navegador não entende um seletor, ele invalida toda a linha de seletores. Isso significa que sua preciosa classe mystyle não é mais azul (para muitos navegadores). O que isso realmente significa? Se, a qualquer momento, você usar uma extensão em que um navegador possa não entender o seletor, todos os outros usos da extensão serão invalidados. Este comportamento também permite aninhamento ruim:

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

Resultado:

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

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

Tl; dr: @extend está perfeitamente ok desde que você nunca o use com nenhum seletor específico do navegador. Se você fizer isso, de repente os estilos serão destruídos, onde quer que você os tenha usado. Tente usar mixins!

clearfix
fonte
4
Nota interessante
simhumileco
4

Use mixins se aceitar um parâmetro, onde a saída compilada mudará dependendo do que você passar para ela.

@include opacity(0.1);

Use extend (com espaço reservado) para quaisquer blocos de estilos repetíveis estáticos .

color: blue;
font-weight: bold;
font-size: 2em;
d4nyll
fonte
0

Concordo totalmente com a resposta anterior da d4nyll. Existe um texto sobre a opção extender e enquanto eu estava pesquisando este tema encontrei muitas reclamações sobre extender, então apenas tenha em mente que e se houver a possibilidade de usar mixin em vez de extender, é só pular extender.

Nesha Zoric
fonte