¿Usar @include vs @extend en Sass?

93

En Sass, no puedo discernir la diferencia entre usar @includecon un mixin y usar @extendcon una clase de marcador de posición. ¿No equivalen a lo mismo?

nombre_usuario_temporal
fuente
2
include no le brinda una clase base extendida, solo agrega opciones. Solo le aconsejo que lea sass-lang.com/docs/yardoc/… y sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend
CodeGroover
1
Además, @CodeGroover, no es un comentario útil en absoluto, tal vez no entendiste la pregunta. La lectura de este da una información más útil: gist.github.com/antsa/970172
temporary_user_name
4
Siempre que utilice un mixin sin parámetro, una extensión será más eficiente. Cortesía de Chris
Abhijeet

Respuestas:

87

Las extensiones no permiten la personalización, pero producen CSS muy 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;
}

Con mixins, obtienes CSS duplicado, pero puedes usar argumentos para modificar el resultado para 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)

Resultados en:

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 ejemplos de código para ver cómo puede hacer que su código sea más limpio y más fácil de mantener utilizando extensiones y mezclas de manera efectiva: http://thecodingdesigner.com/posts/balancing

Tenga en cuenta que, lamentablemente, SASS no permite el uso de extensiones dentro de las consultas de medios (y el ejemplo correspondiente del enlace anterior es incorrecto). En la situación en la que necesita extender según las consultas de medios, use una combinación:

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

La duplicación es inevitable en este caso, pero no debería preocuparse demasiado porque la compresión gzip del servidor web se encargará de ello.

PD Tenga en cuenta que puede declarar clases de marcador de posición dentro de las consultas de medios.

Actualización 2014-12-28 : Extiende la producción de CSS más compacto que los mixins , pero este beneficio disminuye cuando CSS está comprimido con gzip. Si el servidor sirve CSS gzip (que realmente debería!), Y luego se extiende darle casi ningún beneficio. ¡Así que siempre puedes usar mixins ! Más sobre esto aquí: http://www.sitepoint.com/sass-extend-nobody-told-you/

Andrey Mikhaylov - lolmaus
fuente
2
No creo que eso no sea del todo exacto ... puede personalizar @extendsanulando la extensión principal. Por supuesto que no puede pasar argumentos, pero ¿es esa la única diferencia? En ese caso, ¿es @extendsimplemente @mixinsin argumentos? Todavía no veo la ventaja ni la diferencia.
temporary_user_name
2
Aquí hay algunas otras peculiaridades ... stackoverflow.com/questions/30744625/…
Toni Leigh
Sería cuidadoso al interpretar el aspecto de "casi ningún beneficio" del último párrafo. La compresión Gzip es un codificador Huffman basado en diccionario, por lo que si la repetición ocurre lo suficientemente lejos, el texto no estará presente en el diccionario y las proporciones de compresión se verán afectadas. Todavía prefiero siempre @extendque sea posible, ya que esto va a producir CSS más compacto, que todavía se comprima bastante bien (de texto ASCII, después de todo).
amcgregor
@amcgregor, la diferencia es insignificante.
Andrey Mikhaylov - lolmaus
@ AndreyMikhaylov-lolmaus ¡Estoy de acuerdo! Esperaría que la diferencia sea esencialmente inconmensurable a través del cable, independientemente de la elección de cualquier cosa hasta un megabyte o más de CSS generado, aparte del hecho de que el resultado final sin comprimir en la memoria será más compacto de uso @extend. Se trata de una microoptimización aparentemente basada en la intuición y la intuición, en lugar de una comprensión de cómo funciona realmente el esquema de compresión involucrado. (Además: ignora la considerable sobrecarga de la codificación de transferencia gzip bajo demanda; ¡la compresión no es gratuita!;)
amcgregor
18

Un buen enfoque es usar ambos: crear un mixin que le permita mucha personalización y luego hacer extensiones para configuraciones comunes de ese mixin. Por ejemplo (sintaxis 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);
}

Esto le evita llamar al mixin my-button una y otra vez. También significa que no tiene que recordar la configuración de los botones comunes, pero aún tiene la capacidad de crear un botón único y súper único si lo desea.

Tomo este ejemplo de una publicación de blog que escribí no hace mucho tiempo. Espero que esto ayude.

FreddyBushBoy
fuente
12

En mi opinión las extensiones son pura maldad y deben evitarse. He aquí por qué:

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

Se generará el siguiente CSS:

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

Cuando un navegador no comprende un selector, invalida toda la línea de selectores. Esto significa que su preciosa clase mystyle ya no es azul (para muchos navegadores). ¿Qué significa esto realmente? Si en algún momento utiliza una extensión donde un navegador puede no entender el selector, se invalidará cualquier otro uso de la extensión. Este comportamiento también permite la anidación del mal:

%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á perfectamente bien mientras nunca lo use con ningún selector específico del navegador. Si lo hace, de repente derribará los estilos donde sea que lo haya usado. ¡Intenta confiar en mixins en su lugar!

clearfix
fuente
4
Nota interesante
simhumileco
4

Use mixins si acepta un parámetro, donde la salida compilada cambiará dependiendo de lo que le pase.

@include opacity(0.1);

Utilice extender (con marcador de posición) para cualquier bloque de estilos repetible estático .

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

Estoy totalmente de acuerdo con la respuesta anterior de d4nyll. Hay un texto sobre la opción de extensión y mientras investigaba este tema encontré muchas quejas sobre la extensión, así que solo tenlo en cuenta y si existe la posibilidad de usar mixin en lugar de extender, simplemente omite extender.

Nesha Zoric
fuente