Mejora tu código con preprocesadores CSS. SASS.
Siro Ramírez Losada Colaboraciones 29/06/2018
Este artículo ha sido escrito por Javier Rodríguez y publicado originalmente en el blog de Solid GEAR.
Cuando realizamos una página web o una aplicación híbrida, una de las primeras cosas que notamos es que nuestro código CSS suele complicarse y desorganizarse con facilidad a medida que el diseño se complica. CSS, sobre todo en sus primeras versiones, carece de herramientas propias para facilitar la organización y reutilización de propiedades. Es ahí donde surgen los preprocesadores CSS para ayudarnos con esa tarea. En esta entrada en concreto, hablaremos de Sass y mostraremos algunas de sus principales funcionalidades.
¿Qué es un preprocesador CSS?
Un preprocesador CSS es simplemente una herramienta que nos permitirá escribir nuestros estilos en un lenguaje específico y que luego, tras un proceso de compilación, generará unos ficheros CSS con los estilos equivalentes escritos en CSS. Este lenguaje inicial, el cual será diferente según el preprocesador elegido, suele disponer de útiles para facilitar la reutilización y modularización del código.
Así, el uso de un preprocesador es transparente a la página, ya que simplemente escribiremos nuestro código usando el lenguaje del procesador, pero luego en nuestro código HTML enlazaremos la hoja de estilos como siempre.
Existen multitud de procesadores diferentes, aunque probablemente los más conocidos sean Sass y Less. Ambos disponen de funcionalidades parecidas y, aunque en esta entrada hablaremos de Sass, Less (y probablemente muchos otros preprocesadores) son también una buena opción.
Sass
Sass es un preprocesador CSS escrito originalmente en Ruby, aunque actualmente existen otras implementaciones disponibles, como por ejemplo en JavaScript, como se puede ver en su página oficial. Existen dos sintaxis disponibles. Nosotros nos centraremos en la sintaxis SCSS (Sassy CSS) que emplearemos en ficheros .scss.
SCSS es un lenguaje montado sobre el estándar CSS. Eso significa que un fichero SCSS que contenga sólo CSS compilaría sin problemas. Esto facilita enormentente la transición de aplicaciones existentes en CSS a SCSS, ya que inicialmente simplemente tendríamos que compilar los ficheros SCSS con el mismo contenido que los CSSs y usar el CSS generado como hasta entonces.
¿Cómo instalar Sass?
En nuestro caso instalaremos la distribución de JavaScript ya que solemos disponer de Node instalado en nuestros equipos y aprovecharemos npm para ello. Simplemente este comando instalará la última versión disponible.
npm install -g sass
Para compilar todos nuestros ficheros .scss a CSS podremos usar el siguiente comando en el que pondremos la ruta hasta la carpeta en la que están los SCSS y la ruta en la que queremos generar la misma estructura pero en ficheros CSS.
sass ruta/hasta/carpeta/scss:ruta/hasta/carpeta/css
Veamos ahora algunas de las principales ventajas que obtendremos con Sass.
Mejor organizació
Sass permite la anidación de unos selectores dentro de otros. Por ejemplo, si en CSS tenemos unos estilos para el selector nav
y otros para nav .active
podemos meter .active
entro del bloque de nav
(a la vez que por ejemplo añadimos estilos a nav
). Queda más claro viendo el siguiente ejemplo en el que podemos ver cómo sería el fichero CSS tras compilar ese SCSS.
nav {
font-size: 2em;
.active {
font-weight: bold;
}
}
nav {
font-size: 2em;
}
nav .active {
font-weight: bold;
}
Existe otra forma de anidar nuestros estilos también cuando se usa en el selector >
para buscar un elemento directamente bajo otro. Por ejemplo para el selector nav > .active
lo pondríamos de esta manera:
nav {
font-size: 2em;
> active {
font-weight: bold;
}
}
nav {
font-size: 2em;
}
nav > active {
font-weight: bold;
}
También podemos anidar el uso de un selector y del mismo aplicando algún modificador adicional. Por ejemplo podríamos anidar a:hover
dentro de a
, ya que &
tiene el significado del selector del bloque actual.
a {
cursor: pointer;
&:hover {
color: blue;
}
}
a {
cursor: pointer;
}
a:hover {
color: blue;
}
Un caso particular en cuanto a cómo anidar nuestros selectores es el de las media queries. En este caso, en lugar de envolver con @media al selector al que aplica, se introduce dentro de él. Este cambio hace que sea más legible ver cómo cambian las propiedades en función de las restricciones indicadas en la media query.
.card {
width: 50%;
@media only screen and (max-width: 768px) {
width: 100%;
}
}
.card {
width: 50%;
}
@media only screen and (max-width: 768px) {
.card {
width: 100%;
}
}
Por último, también podemos agrupar propiedades de la misma familia (como ocurre por ejemplo con margin, padding, font...) en el que todas tienen una raíz común. En este caso al anidar, para indicar que es una propiedad, usaremos :
al final del prefijo común.
p {
font: {
size: 2em;
weight: bold;
}
}
p {
font-size: 2em;
font-weight: bold;
}
Haciendo uso de todos estos tipos de anidación reforzamos que el equipo agrupe los selectores y propiedades haciendo un código más legible y más organizado.
Reutilización de código
Seguramente la funcionalidades que más nos ayudarán para mejorar la mantenibilidad de nuestro código son aquellas que nos permitan la reutilización de partes del mismo. Sass dispone de diferentes elementos para ello comos por ejemplo variables, mixins o la herencia.
Variables
Al igual que en otros lenguajes una variable simplemente almacenará un valor que podremos usar en otras partes de nuestro SCSS. La variable puede almacenar diferentes tipos de valores, que se corresponden con los que usaríamos en CSS: números, colores, dimensiones... La definición de una variable comienza con $
y su uso es tan sencillo como en el siguiente ejemplo.
$primary-color:black;
$base-font-size: 1em;
body {
background-color: $primary-color;
font-size: $base-font-size;
}
.card {
color: $primary-color;
background-color: invert($primary-color);
font-size: $base-font-size * 1.2;
}
body {
background-color: black;
font-size: 1em;
}
.card {
color: black;
background-color: white;
font-size: 1.2em;
}
Si nos fijamos en el ejemplo hemos definido un par de variables para definir un tamaño de fuente y color base para nuestra web y a partir de ellos vamos generando los estilos. De esta forma si modificamos por ejemplo el color base, este se actualiza acordemente en todos los estilos asociados. En el ejemplo se puede ver también como podemos hacer uso de operadores matemáticos e incluso de funciones (en ese caso invert
que calcula el color opuesto). Si nos hace falta podremos incluso implementar nuestras propias funciones.
Es importante tener en cuenta que, aunque CSS ya dispone de variables, e incluso puede realizar cálculos sencillos, al hacer uso de ellos necesitamos que el navegador empleado tenga una versión en la que ya se soporte dichas funcionalidades. Este problema no ocurre en SCSS ya que la compilación se realiza antes de desplegar nuestra web, por lo que el CSS generado ya no incluirá las variables o funciones, y por ello será transparente al navegador.
Mixins
Un mixin es simplemente un conjunto de propiedades que podremos aplicar en diferentes lugares de nuestro SCSS. Con ellos podremos centralizar nuestra lógica y que nuestro evitar código duplicado en distintos selectores. Además, los mixins admiten parámetros de entrada, por lo que podremos hacer uso de ellos para crear mixins genéricos y personalizar cada estilo cuando hagamos uso de ellos.
El mixin simplemente se define con la palabra clave @mixin
tras la cual definiremos el nombre del mixin y sus variables de entrada si es que tiene. A la hora de usarlo, emplearemos @include
con los parámetros a usar, como se hace en el siguiente ejemplo.
@mixin custom-bar ($background-color, $font-color, $bar-height){
background-color: $background-color;
color: $font-color;
height: $bar-height;
width: 100%;
}
nav {
@include custom-bar(black, white, 2em);
margin-bottom: 1em;
}
footer {
@include custom-bar(black, lightgray, 1.5em);
font-size: 0.8em;
}
nav {
background-color: black;
color: white;
height: 2em;
width: 100%;
margin-bottom: 1em;
}
footer {
background-color: black;
color: lightgray;
height: 1.5em;
width: 100%;
font-size: 0.8em;
}
Herencia
Existe otra forma similar a los mixins para aplicar grupo de propiedades a diferentes selectores, que es la herencia. En la herencia simplemente definiremos las propiedades a heredar dentro de un bloque precedido con %
, y a la hora de usarlo emplearemos la palabra clave @extend
.
%custom-bar {
background-color: black;
color: white;
height: 2em;
width: 100%;
}
nav {
@extend %custom-bar;
margin-bottom: 1em;
}
footer {
@extend %custom-bar;
font-size: 0.8em;
}
footer, nav {
background-color: black;
color: white;
height: 2em;
width: 100%;
}
nav {
margin-bottom: 1em;
}
footer {
font-size: 0.8em;
}
Si comparamos la salida generada con un mixin a la generada con el uso de la herencia, podemos ver cómo el código generado con la herencia parece más compacto y menos repetido. Sin embargo, la herencia tiene la limitación de que no admite variables de entrada.
Modularización
A medida que se complica nuestro diseño podremos dividir nuestros estilos en diferentes ficheros y cargarlos en otros ficheros si así lo necesitamos. Simplemente poniendo @import 'ruta-hasta-el-fichero.css'
, cargaremos toda la información de ese SCSS y sería lo mismo que si tuviéramos el contenido de ese fichero pegado en ese punto.
Eso nos ayuda no sólo para una mejor organización modularizando nuestros estilos, sino que también podremos reusar un mismo módulo en diferentes ficheros. Un caso típico es tener un fichero con las configuración base de nuestra web (con los colores, tamaños...) y cargarlos en todos los ficheros para aplicar los estilos en base a ello.
Este es el caso del popular framework de frontend Bootstrap. Este producto está escrito en SASS y dispone de un fichero SCSS de variables, con el que configura diferentes aspectos claves de la visualización de cada uno de los elementos. Gracias a ello, podremos cargar el fichero principal de Bootstrap en nuestro SCSS (tras habernos descargado los fuentes SCSS de bootstrap) y hacer una sobrecarga de alguna de las propiedades que queramos antes de cargar el fichero SCSS principal. Así dispondremos de un Bootstrap completamente personalizado.
// Sobreescribir variables de Bootrap para personalizarlo
$body-bg: lightgray;
$body-color: brown;
$font-family-base: "Times New Roman", Times, serif;
$headings-line-height: 1.8;
// Importar Bootstrap
@import "path-to-bootstrap-folder/scss/bootstrap";
Conclusiones
Hemos visto como el uso de un preprocesador CSS nos ayuda a organizar mejor nuestro código CSS. Al estar menos duplicado, cumpliremos mejor el principio DRY (Don't Repeat Yourself) y seremos más rápidos tanto al escribirlo por primera vez cómo al realizar futuras modificaciones. Aunque en esta entrada nos hemos centrado en Sass, podemos obtener resultados similares con otras herramientas parecidas, así que os animamos a emplear esta u otra para disfrutar de todas sus ventajas.