ProgramandooIntentándolo

Tutorial Less: 7. Mixins en Less

Logo less

Los mixins son sin lugar a dudas junto a las variables y las funciones una de las características principales de Less, incluso podríamos decir que es el pilar fundamental sobre el que se sustenta porque es con los mixins donde se saca el verdadero potencial de las variables y las funciones.

¿Que es un mixin?

Un mixin es una clase cuya finalidad es ofrecer una funcionalidad que pueda ser reutilizada en otras clases pero que no está pensada para usarse de forma autónoma.

Una definición muy bonita pero quizás no suficientemente clara, he puesto a propósito reutilizada y no heredada porque con un mixin se busca coger una funcionalidad y ponerla donde creamos oportuno pero sin tener que convertir el selector en el que se use en una especialización de la clase padre que es lo que hace el concepto de herencia, y para eso en Less tenemos el extend.

Una forma muy simple de ver el concepto de mixin es ver cuál fue la inspiración para nombrar este concepto en el mundo de la programación y todo viene de una heladería (Steve’s Ice Cream Parlor, Somerville, Massachusetts) en la que vendian los tipicos helados de sabores (nata, vainilla, chocolate, …) aderezado (mezclado) con cookies, frutos secos, nubes, fruta, … y que llamaba “Mix-In”.

Ahora sí que queda claro el concepto de mixin, si a un helado de chocolate le añado unas cookies no se convierte en una cookie hecha con helado, es decir, lo que se quiere es añadir sabores y texturas pero no convertirlo en una cosa distinta.

Sintaxis de los mixins en Less

La forma de definir un mixin no se puede decir que sea muy rompedora, es exactamente la misma que la usada para definir una clase en CSS.


.estoEsUnMixin {
  color: blue;
}

.estoEsOtroMixin() {
  background: #223344;
}

Aunque también puede incluir una pequeña variación que es la inclusión de los paréntesis que además de servir para contener parámetros como veremos más adelante, indican que esa clase no se debe de exportar al CSS cuando se compile por si sola, porque como habíamos visto esa es precisamente la idea de los mixins.

Y si, todas las clases en Less son potencialmente mixins con lo queda muy claro que se quiere facilitar lo máximo posible la reutilización.

E igual que para declararlos, para utilizarlos los paréntesis son opcionales, pero en este caso si el mixin no tiene parámetros no aportan nada más que mantener el mismo formato para que el código sea más claro.


.miClase {
  height: 10px;
  .estoEsUnMixin();
  .estoEsOtroMixin; 
} 

Entendiendo los mixins

Bueno, ya hemos visto que son, para que sirven y como se usan, ahora vamos a ver que pueden contener y como es cual es CSS que generan.

Vamos a empezar por el caso más simple que es que el mixin solo contiene propiedades como cualquier selector, como los 2 mixins anteriores y el CSS que genera este ejemplo es…


.estoEsUnMixin {
  color: blue;
}
.miClase {
  height: 10px;
  color: blue;
  background: #223344;
}

El primer mixin se muestra de formar independiente también porque no tiene paréntesis, el segundo como si los tiene pues no aparece y en .miClase tenemos las propiedades de ambos mixins pero no hay ninguna referencia a de donde vienen ni hay ninguna relación con ellos, es decir, cuando se llama a un mixin se usa solo su contenido, hay que entenderlo como una llamada a una función para usarla tendrá que tener un nombre pero el nombre en si es irrelevante lo importante es el contenido, pues los mixins son “funciones” en Less, como veremos en los siguientes post pueden recibir parámetros y se pueden crear estructuras condicionales e iterativas, pero poco a poco.

¿Los mixins solo pueden tener propiedades? No, dentro de un mixin puede haber tanto propiedades como otros selectores, variables e incluso llamadas a otros mixins.

En este ejemplo tenemos un poco de todo, tiene una propiedad como en el ejemplo anterior, una clase, una pseudo-clase usando el operador &, otro mixin y una variable que además utilizamos también en la clase desde la que usamos el mixin.


.mixinAlto() {
  height: 1000px;
}

.mixinGordo() {
  .mixinAlto();

  width: 2000px;

  .contenido {
    color: #912873;
  } 

  @colorFondo : #564738; 

  &:hover {
    background: @colorFondo; 
  }
}

.contenedor {
  border: 1px solid @colorFondo;

  .mixinGordo();
}

Para entender el resultado, lo más fácil es pensar en que la llamada a un mixin equivale a copiar todo su contenido y con esto en mente pues ya se transforma en CSS.


.contenedor {
  border: 1px solid #564738;
  height: 1000px;
  width: 2000px;
}
.contenedor .contenido {
  color: #912873;
}
.contenedor:hover {
  background: #564738;
}

Por eso podemos utilizar una variable que está declarada en el mixin y que si no estaría inaccesible y haría que fallase la compilación o la pseudo-clase que aplica a .contenedor porque como vimos en primer artículo de este tutorial el operador & hace referencia al selector padre.

Mixins vs Extend

El resultado de usar mixins sin parámetros o extend en muchos casos es el mismo, por lo que a veces se pueden usar de indistintamente, porque lo mismo que hacemos con extend lo podemos conseguir usando un mixin, al contrario esto no es cierto.

El uso de uno o de otro (cuando son intercambiables) es una cuestión de que concepto encaja mejor y del tipo de código que queremos que se genere.


.claseA {
  background: #223344;
  .claseB {
    color: blue;
  }
}

.claseHerencia:extend(.claseA all) {
  height: 10px;
}

.claseMixin {
  height: 10px;
  .claseA();
}

En este ejemplo se puede ver como con la herencia evitamos generar un CSS en el que se repiten las propiedades pero por contra tenemos los estilos fragmentados y con los mixins conseguimos justo lo contrario, aparte de esto con la herencia se ve que unas clases estan relacionadas con otras y con los mixins parecen ser independientes.


// Herencia
.claseA,
.claseHerencia {
  background: #223344;
}
.claseA .claseB,
.claseHerencia .claseB {
  color: blue;
}
.claseHerencia {
  height: 10px;
}

// Mixin
.claseA {
  background: #223344;
}
.claseA .claseB {
  color: blue;
}
.claseMixin {
  height: 10px;
  background: #223344;
}
.claseMixin .claseB {
  color: blue;
}

Por lo tanto podemos quedar en que si la relación de herencia es clara es mejor usar el extend y para el resto de casos pues tenemos los mixin.

El siguiente es un claro ejmplo de herencia.


.boton {
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}

.boton10:extend(.boton) {
  width: 10px;
}

.boton20:extend(.boton) {
  width: 20px;
}

.boton30:extend(.boton) {
  width: 30px;
}

.boton40:extend(.boton) {
  width: 40px;
}

.boton50:extend(.boton) {
  width: 50px;
}

Y como tal el resultado es compacto y tamaño de la hoja de estilos final no aumenta demasiado al añadir nuevas clases a la herencia.


.boton, .boton10, .boton20, .boton30, .boton40, .boton50 {
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton10 {
  width: 10px;
}
.boton20 {
  width: 20px;
}
.boton30 {
  width: 30px;
}
.boton40 {
  width: 40px;
}
.boton50 {
  width: 50px;
}

Con los mixins el código Less es quizás algo menos claro pero no mucho pero al ver el CSS final rápidamente se ve que no es la mejor opción.


.boton {
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}

.boton10 {
  width: 10px;
  .boton;
}

.boton20 {
  width: 20px;
  .boton;
}

.boton30 {
  width: 30px;
  .boton;
}

.boton40 {
  width: 40px;
  .boton;
}

.boton50 {
  width: 50px;
  .boton;
}

.boton {
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton10 {
  width: 10px;
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton20 {
  width: 20px;
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton30 {
  width: 30px;
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton40 {
  width: 40px;
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}
.boton50 {
  width: 50px;
  border: 1px solid #000;
  border-radius: 10px;
  font-size: 10px;
}

Con esto podemos concluir que con la herencia el CSS final es más compacto, lo que hablando claro, viene a ser mejor pero usar la herencia pero tener por ejemplo una clase boton que herede de .bordeGrande, .sombreadoOscuro y .fondoClaro por ejemplo no deja de ser raro y aunque es valido no es correcto desde el punto de vista de tener unos estilos coherentes y entendibles.

En el proximo post seguiremos con los mixins con parametros, y como siempre aquí tienes el enlace para descargar un archivo .less con todos los ejemplos.