"El buen diseño es obvio. El gran diseño es transparente"
- Joe Sparano

Funciones y Mixins en Sass

6 minutos de lectura
Fecha: 14/7/2017

Siendo actualmente Sass el preprocesador de css más utilizado, vamos a analizar dos de las directivas que más potencia le proporcionan y que lo hacen imprescindible a la hora de mantener un proyecto de grandes dimensiones, estamos hablando de las Funciones y Mixins en Sass.

Los Mixins y las funciones en Sass son básicos para la reutilización de estilos, y para dotar de cierta modularidad a nuestro código, pero tienen ciertas diferencias, vamos a analizarlos por separado para ver que nos dan, y que no.

Mixins

Los mixins como decíamos nos permiten reutilizar estilos en nuestro código sin tener que (en caso de que estemos usando sass) andar definiendo clases por el código y luego incrustandolas ya sea usando placeholders o extendiéndolas.

Al igual que sucede en el caso de las funciones nos permiten pasarles parámetros para poder alterar su comportamiento y que sean más dinámicos, ya que además de usarlos como parámetros de control para modificar el flujo del código, o como variables que podremos interpolar para trabajar con ellas.

Respecto a su sintaxis debemos recordar que para declararlos hay que escribir @mixin, y para más tarde utilizarlos en el código se llaman con @include. Veamoslo una serie de ejemplos prácticos, vamos a crear un mixin que cree los estilos de una caja de color rojo que ocupe todo el ancho y 100px de alto…

@mixin crea-caja {
  box-sizing: border-box;
  background-color: red;
  width: 100%;
  height: 100px;
  padding: 20px;
}

Este mixin contiene únicamente los atributos para hacer lo que digo de modo que para usarla supongamos que en un div con una clase llamada «box» haríamos esto

.box {
  @include crea-caja;
}

Pero como decíamos los mixins nos valen para reutilizar estilos, y hasta ahora hemos puesto solo atributos, también podriamos poner selectores para de esta manera que genere todo el código anterior:

@mixin crea-caja {
  .box {
    box-sizing: border-box;
    background-color: red;
    width: 100%;
    height: 100px;
    padding: 20px;
  }
}

Para ver que podemos meter dentro cualquier estilo css, pensemos en que ahora queremos que ademas al pasar el ratón por encima el cursor cambie como si se tratara de un link

@mixin crea-caja {
  .box {
    box-sizing: border-box;
    background-color: red;
    width: 100%;
    height: 100px;
    padding: 20px;
    &:hover{
      cursor: pointer;
    }
  }
}

Vamos a comenzar a ver como pasarles parametros, imaginemos que queremos crear cajas de distintos colores de forma dinámica usando esto, donde el primer parametro es el color de fondo y el segundo se interpola en el nombre de la clase, y que además si no se lo paso los parametros tenga un valor por defecto (esto ya empieza a complicarse).

@mixin crea-caja($color: #26619C, $name: lapislazuli) {
  .box-#{$name} {
    box-sizing: border-box;
    background-color: $color;
    width: 100%;
    height: 100px;
    padding: 20px;
    &:hover{
      cursor: pointer;
    }
  }
}

Ahi tenemos el mixin, ahora ¿que pasaría si lo llamaramos de distintas maneras?

@include crea-caja;
@include crea-caja(#F00, rojo);
@include crea-caja(#AAA, gris);

El código que genera es el siguiente:

.box-lapislazuli {
  box-sizing: border-box;
  background-color: #26619C;
  width: 100%;
  height: 100px;
  padding: 20px; }
  .box-laspislazuli:hover {
    cursor: pointer; }

.box-rojo {
  box-sizing: border-box;
  background-color: #F00;
  width: 100%;
  height: 100px;
  padding: 20px; }
  .box-rojo:hover {
    cursor: pointer; }

.box-gris {
  box-sizing: border-box;
  background-color: #AAA;
  width: 100%;
  height: 100px;
  padding: 20px; }
  .box-gris:hover {
    cursor: pointer; }

No hacen falta muchas explicaciones, el primero al no pasarle parametro usa el que declaramos por defecto en el mixin y los otros dos como deciamos interpolan dentro del selector el parametro y lo usan para definir el atributo background-color.

Aunque podemos complicar aun más la logica de nuestro mixin cerramos su analisis mostrando una ultima caracteristica tambien muy interesante, la posibilidad de pasarle un bloque entero de reglas CSS, el cual se añadirá dentro de mixin donde posicionemos la directiva @content, veamoslo.

@mixin crea-caja($color: #26619C, $name: lapislazuli) {
  .box-#{$name} {
    @content;
    box-sizing: border-box;
    background-color: $color;
    width: 100%;
    height: 100px;
    padding: 20px;
    &:hover{
      cursor: pointer;
    }
  }
}

Si nos fijamos unicamente escribimos en un punto del mixin el @content; con esto conseguimos lo siguiente, podemos lanzar el mixin de esta manera en nuestro código…

@include crea-caja(#F00, rojo) {
  border: 2px solid #700;
  &:hover{
    border: 2px solid #400;
    background-color: #B00;
  }
}

Y el css resultante sería este.

.box-rojo {
  border: 2px solid #700;
  box-sizing: border-box;
  background-color: #F00;
  width: 100%;
  height: 100px;
  padding: 20px; }
  .box-rojo:hover {
    border: 2px solid #400;
    background-color: #B00; }
  .box-rojo:hover {
    cursor: pointer; }

Funciones

El uso de las funciones es más moderno que el de los mixins ya que llegaron despues, fueron incluidas en la versión 3.1.0, y al ver lo que podemos hacer con un mixin lo más seguro es que ya nos esperemos que las funciones sean muy parecidas.

Esto es cierto y de hecho el propio lenguaje ya incluye un amplio abanico que podemos utilizar, actualmente en la documentación oficial las dividen en:

  1. Funciones RGB
  2. Funciones HSL
  3. Funciones de opacidad
  4. Funciones sobre cadenas
  5. Funciones sobre números
  6. Funciones sobre listas
  7. Funciones sobre maps
  8. Funciones sobre selectores
  9. Funciones de introspección
  10. Miscelanea

Si queremos saber cuales son y como se usan podemos ver la documentación oficial aqui.

No es necesario que expliquemos que hace cada uno de estos tipos de funciones salvo el ultimo apartado, este tal vez no sepamos para que vale porque los maps son un tipo de dato relativamente moderno, de hecho se añaden en la versión 3.3 del lenguaje de manera que salieron aun después que las propias funciones… Para no desviarnos ya que hablaremos de ellos en otro post solamente deciros que es un dato muy parecido a un objeto javascript o al formato de un JSON.

Pero lo realmente interesante de las funciones además de todas las que tenemos ya disponibles es que podemos crearnos las nuestras, la manera en este caso es para declararlos es escribiendo @function, y para después llamarlos lo hacemos directamente como llamaríamos a una función en javascript por ejemplo.

Esta es la primera diferencia con un mixin en el cual teniamos que usar una directiva para ejecutarlo.

Otra diferencia con los mixins a la hora de llamarlos es que mientras que un mixin sin parámetros se invoca solo con el nombre del mismo tras la directiva, en el caso de las funciones tenemos que usar los paréntesis siempre, mira el siguiente ejemplo.

//DECLARAMOS LOS MIXINS
@mixin mixin-sin-parametros {
  .box {
    background-color: #FF0;
    width: 100%;
    height: 100px;
    padding: 20px;
  }
}
@mixin mixin-con-parametros($color: #26619C, $name: lapislazuli) {
  .box-#{$name} {
    background-color: $color;
    width: 100%;
    height: 100px;
    padding: 20px;
  }
}
//LLAMAMOS A LOS MIXINS
@include mixin-sin-parametros;
@include mixin-con-parametros(#F00, rojo);


//DECLARAMOS LAS FUNCIONES
@function funcion-sin-parametros() {
  @return 500px;
}
@function funcion-con-parametros($num: 1000px) {
  @return $num/2;
}
//LLAMAMOS A LAS FUNCIONES
@include funcion-sin-parametros;
@include funcion-con-parametros(1500px);

En este ejemplo las diferencias se pueden ver claras, además las funciones como vemos necesitan la directiva @return para retornar un valor, al igual que los mixins se pueden crear funciones sin parámetros aunque es bastante raro ya que precisamente la gracia esta en manipular los datos y retornar un valor, de modo que lo normal es que usemos esos parámetros para pasar los datos.

De hecho a día de hoy de todo ese montón de funciones que ya trae sass solamente una es una función sin parámetros, es la funcion unique-id() que vale para devolver un identificador CSS único, personalmente tampoco se me ocurren muchas mas utilidades que esta para una función que no use parámetros.

Tampoco es que un mixin sin argumentos nos vaya a servir de mucho, así que en esto son parecidos.

Conclusiones

Mixins y Funciones son parecidos, los dos pueden acceder a variables globales y a ambos podemos pasarles o no parametros, en ambos casos podemos definirles valores por defecto a estos, a los dos se les puede pasar un numero variable de argumentos y su potencia reside en la capacidad que tienen de usar estos parametros para hacer cierta logica y devolver un resultado.

Obviamente se declaran y se llaman como vimos de formas distintas, y la diferencia es que los mixins estan enfocados para la generación de bloques de selectore y reglas CSS, y las funciones por su parte son más utilizadas para manipular los datos de entrada y tras realizar las operaciones devolver un resultado.

Creo que con este ultimo ejemplo veremos clara los casos de uso de cada uno, pensemos en que queremos crear la misma caja de antes con todas las reglas que tenia, modificandole el nombre de forma dinámica, etc. Pero además ahora queremos que los colores que le asignamos sigan unas pautas:

  • El color al pasar por encima el puntero tiene que ser un 5% más oscuro
  • El color del borde tiene que ser un 10% más oscuro
  • El color del borde al pasar por encima el puntero tiene que ser un 20% más oscuro

Mientras que para generar todo el bloque de codigo css lo correcto es seguir usando un mixin, para la gestion de los colores usamos una función nativa de sass llamada darken, este es el resultado…

@mixin crea-caja($color: #26619C, $name: lapislazuli) {
  .box-#{$name} {
    @content;
    box-sizing: border-box;
    background-color: $color;
    border: darken($color, 10%);
    width: 100%;
    height: 100px;
    padding: 20px;
    &:hover{
      border: darken($color, 20%);
      background-color: darken($color, 5%);
      cursor: pointer;
    }
  }
}

//LO LLAMAMOS
@include crea-caja(#F00, rojo);

Y el resultado es este…

.box-rojo {
  box-sizing: border-box;
  background-color: #F00;
  border: #cc0000;
  width: 100%;
  height: 100px;
  padding: 20px; }
  .box-rojo:hover {
    border: #990000;
    background-color: #e60000;
    cursor: pointer; }

Además os comento que ya existen librerías de mixins y funciones como Compass o Bourbon donde podremos encontrar la mayoría de las funcionalidades que necesitamos y otras muchas, os dejo un enlace a un post donde hablo sobre la librería Bourbon.

Hasta aquí el post, a mi juicio de todo lo que os puedo contar de sass estas son las funciones más potentes del lenguaje, pero existen muchas otras, no dejes de leer la documentación y en siguientes entradas del blog iremos explicando algunas otras!