Introducción a SASS

25 de febrero 2019ComentarioscssDavid Poza SuárezComentarios

Sass es un acrónimo para Syntactically Awesome Stylesheets, y hace referencia a un preprocesador de hojas de estilo que viene a otorgar poderes al estático y poco práctico lenguaje CSS, convirtiéndolo en un lenguaje de scripting. Gracias a Sass disponemos de variables, sentencias de control y funciones entre otras características, que van destinadas a escribir sin repetirse y reutilizando todo el código lo posible.

Para empezar diremos que existen dos versiones de Sass, la antigua (con extensión .sass) que usaba indentación para separar los bloques, y la nueva, que usa llaves al igual que la sintaxis estándar de CSS (con extensión .scss), por lo que resulta mucho más familiar y es la que vamos a usar en este artículo.

Ahora sí, comencemos con esta pequeña y breve aproximación a lo que nos ofrece Sass.

Variables

Imaginemos que hemos definido una paleta de colores basada en 4 colores principales, que vamos a repetir continuamente en los diferentes elementos de la web. Ahora imagina que el cliente te pide que cambies la paleta de colores... Tendrás que ir modificando todas las apariciones de esos 4 colores, lo que no facilita el cambio y además aumenta las posibilidades de cometer errores.

Lo bonito de las variables es que dotan de un significado a los valores que almacenan y además permiten reutilizar código.

Se definen así:

$variable: 5px;

Comentarios

Tenemos comentarios de varias líneas que serán volcados al css final:

/\*
comentario de
varias líneas
\*/

Pero también tenemos comentarios de una sola línea, que en este caso no se volcaran al css final.

// comentario de una sola línea

Anidamiento de selectores

En css cuando queremos apuntar a un elemento contenido dentro de otro usamos la sintaxis:

.widget {
   padding: 5px;
   background-color: lightgrey;
}

.widget ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.widget li {
    display: inline-block;
}

Pero es evidente que visualmente sería mejor representar dicha sintaxis de forma jerárquica.

.widget {
   padding: 5px;
   background-color: lightgrey;

   ul {
	    margin: 0;
	    padding: 0;
	    list-style: none;

	    li {
    		display: inline-block;
		}
	}
}

Anidamiento de propiedades

De nuevo para evitar repetir código podríamos tener un selector que repite muchas propiedades relacionadas con la fuente. Podemos ahorrar código del siguiente modo:

.selector{
    background-color: lightgrey;
    font: {
        family: georgia;
        size: 2.4em;
        weight: bold;
    }
}

Interpolación de variables

Antes de continuar, tenemos que aclarar este concepto porque vamos a verlo continuamente.

La interpolación nos va a permitir usar el contenido de una variable para definir el identificador de un selector o de una propiedad. Se usa la sintaxis #{$variable}.

$selector: rojo;
$propiedad: color;
$valor: red;

.fondo-#{$selector} {
    background-#{$propiedad}: $valor;
}

///////////////

.fondo-rojo {
  background-color: red;
}

Ampersand &

Este símbolo se usa para hacer referencia al nombre del selector dentro de su propio bloque, para así no tener que escribirlo continuamente. Un ejemplo con paseudoclases sería:

.button {
  &:visited { }
  &:hover { }
  &:active { }
}
// equivale al css:
.button:visited { }
.button:hover { }
.button:active { }

Mixins

Los mixins guardan similitud con las funciones. Y como ya sabemos, son la base de la reutilización de código. Se definen usando la palabra reservada @mixin, como sigue:

@mixin my\_mixin($param1, $param2){
    background-color: $param1;
    padding: $padding2;
}

// Después solo queda "llamarlo" o incluirla desde otro lugar

.clase{
    ....
   @include my\_mixin(lightgrey, 5px);
}

Algunas funciones nativas de SASS

  • rgb($red, $green, $blue): Define un color con sus componentes roja, verde y azul
  • rgba($red, $green, $blue, $alpha): Lo mismo pero además incluyendo el canal alpha
  • red($color): Obtiene la componente roja de un color.
  • green($color)
  • blue($color)
  • hsl($hue, $saturation, $lightness): Define un color a partir de su tono, saturación y luminosidad.
  • lighten($color, $amount): Aclara un color dando por ejemplo un valor de cantidad en porcentaje: 20%
  • darken($color, $amount)
  • complement($color): Obtiene color complementario al color dado
  • invert($color): Obtiene el color opuesto al color dado.
  • to-upper-case($string)
  • to-lower-case($string)
  • percentage($number): Convierte un número sin unidades a porcentaje, por ejemplo percentage(0.5) => 50%
  • round($number)
  • ceil($number)
  • floor($number)
  • abs($number)
  • min($numbers…): Devuelve el menor de los elementos de una lista.
  • max($numbers…)
  • random([$limit]): Devuelve un número aleatorio entre 1 y 100, pero si pasamos el parámetro opcional entonces podemos cambiar el límite superior.
  • length($list): Devuelve la longitud de una lista de elementos
  • nth($list, $n) : obtiene en elemento n de la lista
  • join($list1, $list2, [$separator]): Compone una cadena concatenando dos listas, pudiendo usar un carácter intermedio en la unión. Ej: join((blue, red), (#abc, #def), space) => blue red #abc #def
  • if($condition, $if-true, $if-false)

Aqui podemos encontrar la lista completa: http://sass-lang.com/documentation/Sass/Script/Functions.html

Nuestras propias funciones

Lo primero es saber que para llamar a una función debemos haberla definido más arriba, ya que el fichero se procesa en orden.

@function numero($num: 500px){ //podemos indicar un valor default para los parametros.
  @return  $num/2;
}

.uno {
  width: numero(); //llamamos a la funcion definida arriba
  background-color: orange;
  text-align: center;
}

Estructuras de control

@if y @else

$color: primary;
p {
  @if $color == primary {
    color: blue;
  } @else if $type == secondary {
    color: red;
  } @else {
    color: black;
  }
}

@for

En el bucle for si usamos la palabra reservada through se incluye el índice límite como última iteración, mientras que si usamos la palabra to, esa última iteración no se realiza.

$classname: col

@for $i from 1 through 4{
  .#{$classname}-#{$i} {
      width: 60px + $i
  }
}

//compila a css como:

.col-1 {
  width: 61px;
}

.col-2 {
  width: 62px;
}

.col-3 {
  width: 63px;
}

.col-4 {
  width: 64px;
}

@each

Es como el @for pero recorriendo listas o también mapas.

@each $var in red, green, blue{
    .title-#{$var}{
        background-color: #{$var};
    }
}

// SU SALIDA:

.title-red {
  background-color: red;
}

.title-green {
  background-color: green;
}

.title-blue {
  background-color: blue;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//o también podríamos especificar un map almacenado en una variable, siendo un conjunto de tuplas clave->valor

$values:(
  rojo: red,
  verde: green,
  azul: blue
);
@each $key,$value in $values{
    .title-#{$key}{
        background-color: #{$value};
    }
}

//SU SALIDA:
.title-rojo {
  background-color: red;
}

.title-verde {
  background-color: green;
}

.title-azul {
  background-color: blue;
}

@while

En el bucle while somos nosotros quienes especificamos la operación de avance del bucle, por lo que si no lo hacemos correctamente provocaremos un bucle infinito.

$ancho: 1;

@while $ancho <= 12 {
  .ancho-#{$ancho} {
    width: (100% / 12) \* $ancho
  }
  $ancho: $ancho + 1
}

Inclusión de archivos parciales

La posibilidad de separar las hojas de estilo en varios ficheros suena muy interesante, así podemos ser más organizados y tal vez reutilizar ciertos módulos. Pero es que además cuando todo se compila finalmente, nos encontraremos con un único fichero css y por tanto una sola petición http.

Los ficheros parciales (ficheros que vamos a incluir en el principal), deben empezar con un símbolo underscore, que indica al preprocesador sass que no debe convertirse a css ese fichero, porque primeramente va a ser importado. Un ejemplo de fichero parcial sería: _defautls.scss

Para importar un fichero parcial usamos la instrucción @import 'defaults', sin indicar el underscore ni la extensión, pues ambos están implícitos.

Extender un elemento

Otro ejemplo de reutilización de código es cuando tenemos selectores que comparten ciertas propiedades y por lo tanto no deseamos tener que escribirlas repetidas en cada uno de ellos. Para copiar las propiedades que queremos "heredar" de un selector a otro usaremos la instrucción @extend.

.padre{
    padding: 20px;
    background-color: lightgrey;
    color: grey;
}

.hijo{
    @extend .padre;
    border: 1px solid black;
}

Media queries

En el css estándar resulta muy poco práctico tener que especificar las media queries por separado, encontrandolas normalmente al final del fichero, por lo que nos obliga a ir buscandolas de arriba para abajo.

Con sass podemos incluir la media query dentro del mismo selector, para tener así todas sus versiones por dispositivo contenidas dentro de sí mismo.

$small-device: 576px;
$medium-device: 768px;
$large-device: 992px;
$extra-large-device: 1200px;

.selector {
    float: left;
    width: 250px;
    @media screen and (max-width: $small-device) {
      width: 100px;
      float: none;
    }
    @media screen and (min-width: $large-device) {
      float: right;
    }
}

Conclusión

Tal es la potencia y mejora del flujo de trabajo que nos otorga a la hora de diseñar el frontend de nuestras aplicaciones web, que no es de extrañar que frameworks tan importantes como Bootstrap se hayan decantado por Sass frente a tu competencia directa Less, otro precompilador de hojas de estilo.

Documentación

La documentación oficial de sass podemos encontrarla aquí: https://sass-lang.com/documentation/ y este otro manual también es útil: https://uniwebsidad.com/libros/sass

Además disponemos de un compilador de sass a css online en esta url: https://www.sassmeister.com/. Nos será muy útil cuando estemos estudiando.