Apéndice B. Preprocesadores
El uso de un preprocesador es una parte vital de un flujo de trabajo CSS moderno. Un preprocesador proporciona una serie de comodidades para agilizar su escritura y ayudarlo a mantener su base de código. Por ejemplo, puede escribir un fragmento de código una vez y luego reutilizarlo en su hoja de estilo.
Un preprocesador funciona tomando un archivo fuente, que usted escribe, y traduciéndolo en un archivo de salida, que es una hoja de estilo CSS normal. En la mayoría de los casos, el archivo de origen se parece mucho al CSS normal, pero con características adicionales agregadas. Un ejemplo simple que usa una variable de preprocesador se ve así
$brand-blue: #0086b3;
a:link {
color: $brand-blue;
}
.page-heading {
font-size: 1.6rem;
color: $brand-blue;
}
Este fragmento de código define una variable nombrada $brand-blue
, que se usa en dos lugares separados más adelante en la hoja de estilo. Cuando se ejecuta a través del preprocesador de Sass, la variable se reemplaza en toda la hoja de estilo, produciendo el siguiente CSS como salida:
a:link {
color: #0086b3;
}
.page-heading {
font-size: 1.6rem;
color: #0086b3;
}
Es importante tener en cuenta que, debido a que la salida final es CSS normal, un preprocesador no agrega características nuevas al idioma en lo que respecta al navegador. Sin embargo, le proporciona comodidades útiles como desarrollador.
En el ejemplo, usar una variable para representar el color le permite reutilizar el color innumerables veces sin tener que copiar y pegar el código hexadecimal exacto. El preprocesador realiza la copia por usted cuando genera el archivo de salida. También significa que puede editar el valor en un solo lugar y hacer que ese cambio se propague por toda la hoja de estilo.
Los dos preprocesadores más populares son Sass (httpss://sass-lang.com/) y Less (https://lesscss.org/), aunque también hay varios otros. Sass es el más popular, así que me centraré principalmente en eso en este apéndice. Pero Sass y Less son similares, con diferencias sintácticas en su mayoría menores que los distinguen entre sí. Por ejemplo, Sass usa un $
para denotar variables ($brand-blue)
, mientras que Less usa un @
(@brand-blue)
. Todas las funciones de Sass que se tratan en este apéndice también se admiten en Less; consulte la documentación de Less para ver las diferencias de sintaxis.
B.1 Sass
Al comenzar con Sass, deberá tomar algunas decisiones. Primero es qué implementación usar. Sass está escrito en Ruby, pero esta implementación es un poco lenta cuando se compilan hojas de estilo grandes, por lo que recomiendo algo llamado LibSass, que es un puerto C/C++ del compilador Sass.
Si se siente cómodo con JavaScript y el entorno Node, puede obtener LibSass instalando el paquete node-sass a través del administrador de paquetes npm. Si aún no tiene Node.js instalado, puede encontrarlo (es gratis) en https://nodejs.org. Descárguelo e instálelo de acuerdo con las instrucciones que se dan allí. Le mostraré los comandos necesarios para esto, pero si desea obtener más información sobre npm o necesita ayuda para solucionar cualquier problema, visite https://docs.npmjs.com/getting-started/.
B.1.1. Instalación de Sass
Para instalar Sass, cree un nuevo directorio de proyecto y navegue hasta él en su terminal. Luego ejecute los siguientes dos comandos:
npm init
- y Inicializa un nuevo proyecto npm, creando un archivo package.json. Consulte el Capítulo 10 (sección 10.1.1) para obtener más información sobre este archivo.npm install --save-dev node-sass
- Instala el paquetenode-sass
y lo agrega a package.json como una dependencia de desarrollo.
La segunda decisión que deberá tomar es qué sintaxis utilizar. Sass admite dos: Sass y SCSS. Ambos ofrecen las mismas características, pero la sintaxis de Sass omite todos los rizos.llaves y punto y coma, usando estrictamente sangría para indicar la estructura de su código. Por ejemplo:
body
font-family: Helvetica, sans-serif
color: black
Esto es similar a los lenguajes de programación con espacios en blanco significativos, como Ruby y Python. La sintaxis de SCSS usa llaves y punto y coma, por lo que se parece más al CSS normal. Por ejemplo:
body {
font-family: Helvetica, sans-serif;
color: black;
}
SCSS se usa más comúnmente. Si no está seguro, le sugiero que utilice SCSS, que es lo que utilizaré en este apéndice.
B.1.2. Corriendo Sass
Ahora que Sass está instalado, usémoslo para crear una hoja de estilo. En el directorio de su proyecto, cree dos subdirectorios llamados sass y build. Colocará sus archivos fuente en el directorio sass, y Sass usará esos archivos para producir un archivo CSS en el directorio de compilación. A continuación, edite el archivo package.json. Cambie la scriptsentrada para que coincida con este listado.
"scripts": {
"sass": "sass sass/index.scss build/styles.css"
},
Listado B.1. Agregar un comando sass a package.json
Esto define un comando sass
que, cuando se ejecuta, compila el archivo en sass/index.scss en un nuevo archivo en build/styles.css. El archivo sass/index.scss aún no existe en su proyecto. Adelante, créalo. Tu código Sass entrará en este archivo. La ejecución npm run sass
ejecuta el comando, produciendo (o sobrescribiendo) la hoja de estilo en build/styles.css.
Los complementos como gulp-sass
están disponibles para corredores de tareas comunes como Grunt, Gulp y Webpack. Si desea utilizar un complemento, busque uno que integre Sass o Less en el flujo de trabajo con el que esté más familiarizado.
B.1.3. Comprender las características importantes de Sass
Te he mostrado un ejemplo de una variable Sass ($brand-blue)
. Agregue el código en la siguiente lista a su archivo index.scss para que Sass lo compile.
$brand-blue: #0086b3; 1
a:link {
color: $brand-blue; 2
}
.page-heading {
font-size: 1.6rem;
color: $brand-blue; 3
}
Listado B.2. Una variable de Sass
- Define una variable
- Usa la variable
- Usa la variable
Ejecutar npm run sass
para compilar esto en CSS. El archivo de salida (build/styles.css) se verá así:
a:link {
color: #0086b3; }
.page-heading {
font-size: 1.6rem;
color: #0086b3; }
/*# sourceMappingURL=styles.css.map */
Las variables se han reemplazado con el valor hexadecimal, por lo que ahora el navegador puede entenderlo. Sass también produjo un archivo de mapa de origen y agregó un comentario al final de la hoja de estilo, dando una ruta al mapa de origen.
mapa fuente: un archivo que la computadora usa para rastrear cada línea de código generada (CSS, en nuestro caso) hasta el código fuente que lo produjo (Sass). Algunos depuradores pueden utilizar este archivo de mapa, incluidas las DevTools del navegador.
Tenga en cuenta que el código compilado no tiene un formato tan limpio; las llaves de cierre se colocan en la línea anterior y, en algunos casos, se eliminan las líneas vacías. Esto está bien porque los espacios en blanco no son importantes para el navegador. Pero, para el resto de los ejemplos en este apéndice, limpiaré el formato de salida para que su significado sea claro.
Computación en línea
Sass también soporta aritmética en línea usando +, -, *, /, y % (para la división modular). Esto le permite derivar varios valores a partir de un valor de origen, como se muestra a continuación.
$padding-left: 3em;
.note-author {
left-padding: $padding-left; 1
font-weight: bold;
}
.note-body {
left-padding: $padding-left * 2; 2
}
Listado B.3. Usar cálculos en línea
- Usa una variable
- Multiplica la variable por dos
Úse npm run sass
para compilar esto, que produce la salida:
.note-author {
left-padding: 3em;
font-weight: bold;
}
.note-body {
left-padding: 6em;
}
Esta función es útil cuando dos valores están relacionados, pero no son iguales. En este caso, a note-body
siempre tendrá el doble de relleno izquierdo que a note-author
, independientemente del valor de $padding-left
.
Selectores anidados
Sass le permite anidar selectores dentro de otros bloques de declaración. Puede utilizar el anidamiento para agrupar el código relacionado en el mismo bloque, como se muestra aquí.
.site-nav {
display: flex;
> li { 1
margin-top: 0;
&.is-active { 2
display: block;
}
}
}
Listado B.4. Selectores de anidamiento
- Selector anidado
- Ampersand indica dónde se agregará el selector externo.
Sass fusiona selectores anidados con los selectores de los bloques de declaración externos. Este ejemplo se compila para:
.site-nav {
display: flex;
}
.site-nav > li {
margin-top: 0;
}
.site-nav > li.is-active {
font-weight: bold;
}
De forma predeterminada, el selector .site-nav
externo se antepone a cada selector en el código compilado y se agrega un espacio donde se unen los selectores. Para cambiar esto, use un ampersand (&) para indicar dónde desea que se inserte el selector externo.
El anidamiento aumenta la especificidad de los selectores resultantes. Tenga cuidado al anidar y evite anidar a varios niveles de profundidad.
html {
font-size: 1rem;
@media (min-width: 45em) { 1
font-size: 1.25rem;
}
}
Listado B.5. Anidar una consulta de medios
- Consulta de medios dentro de un bloque de declaración
Esto se compila a:
html {
font-size: 1rem;
}
@media (min-width: 45em) {
html {
font-size: 1.25rem;
}
}
De esta forma, si cambia un selector, no tendrá que acordarse de cambiar el selector correspondiente en una consulta de medios para que coincida.
Parciales (@import)
Los parciales le permiten dividir sus estilos en varios archivos separados, y Sass los concatenará todos juntos en un solo archivo. Con los parciales, puede organizar sus archivos como desee, pero solo sirve un archivo al navegador, lo que reduce la cantidad de solicitudes de red.
Cree un nuevo archivo en su proyecto como sass/button.scss. Agregue los estilos que se muestran aquí a este archivo.
.button {
padding: 1em 1.25em;
background-color: #265559;
color: #333;
}
Luego, en index.scss, importe la hoja de estilo parcial usando la @import
a la regla como se muestra aquí.
@import "button"; 1
- Ruta al archivo parcial
Cuando ejecute Sass, el archivo parcial se compilará e insertará donde indicó con la regla @import
.
En mi opinión, esta es la característica más importante de un preprocesador. A medida que su hoja de estilo crece, resulta difícil de manejar desplazarse por miles de líneas de código para encontrar la parte apropiada de la hoja de estilo. Esta función le permite dividir la hoja de estilo en pequeños módulos lógicos, sin incurrir en una pérdida de rendimiento en la red. Consulte la barra lateral "Preprocesadores y CSS modular" en el capítulo 9 para obtener más información al respecto.
Mixins
Un mixin es una pequeña parte de CSS que puede reutilizar en su hoja de estilo. Esto es útil cuando tiene un estilo de fuente en particular que necesita hacer coincidir en varios lugares, o para reglas que se repiten comúnmente, como clearfix
(discutido en el capítulo 4 , sección 4.2).
Un mixin se define usando una regla @mixin
y se usa con una regla @include
. Aquí hay un ejemplo de un mixin clearfix.
@mixin clearfix { 1
&::before { 2
display: table;
content: " ";
}
&::after { 2
clear: both;
}
}
.media {
@include clearfix; 3
background-color: #eee;
}
Listado B.8. Mixin Clearfix
- Define un mixin llamado clearfix
- Selectores anidados
- Aplica el mixin
El preprocesador toma el código del mixin y lo copia en lugar de la regla @include
. El código resultante se ve así:
.media {
background-color: #eee;
}
.media::before {
display: table;
content: " ";
}
.media::after {
clear: both;
}
Tenga en cuenta que no se menciona clearfix
en el código resultante. El contenido del mixin solo se agrega a la hoja de estilo en el lugar o lugares donde se usa.
También puede definir mixins que toman parámetros, al igual que una función en la programación convencional. La siguiente lista muestra un mixin que define un cuadro de alerta. Toma dos parámetros, $color
y $bg-color
, que son variables definidas dentro del alcance del mixin.
@mixin alert-variant($color, $bg-color) { 1
padding: 0.3em 0.5em;
border: 1px solid $color; 2
color: $color; 2
background-color: $bg-color; 2
}
.alert-info {
@include alert-variant(blue, lightblue) 3
}
.alert-danger {
@include alert-variant(red, pink) 3
}
Listado B.9. Mixin con parámetros
- Define un mixin con dos parámetros
- Se pueden utilizar 2 variables de parámetro dentro del mixin.
- Pasa valores al mixin
Cada vez que se usa el mixin, se pasan valores diferentes. Estos valores se asignan a las dos variables en consecuencia. Este fragmento produce la siguiente salida CSS:
.alert-info {
padding: 0.3em 0.5em;
border: 1px solid blue;
color: blue;
background-color: lightblue;
}
.alert-danger {
padding: 0.3em 0.5em;
border: 1px solid red;
color: red;
background-color: pink;
}
Nuevamente, el mixin le permite reutilizar el mismo fragmento de código varias veces, pero en este caso, produjo dos variaciones del mismo código. Estas diferencias se basan en los valores que pasó.
Históricamente, un uso común de los mixins ha sido mezclar versiones de una propiedad con prefijo de proveedor. Por ejemplo, un border-radius
mixin podría especificar las propiedades -webkit-border-radius
, -moz-border-radius
y border-radius
. Te animo a que no uses mixins para esto; utilice Autoprefixer en su lugar (para obtener más información sobre esto, consulte la sección "PostCSS" más adelante en este apéndice).
Ampliar
Sass también es compatible con una regla @extend
. Esto es similar a un mixin, pero la forma en que se compila es diferente. En lugar de copiar las mismas declaraciones varias veces, Sass agrupa a los selectores para que estén todos en el mismo conjunto de reglas. Esto se explica mejor con un ejemplo. En la siguiente lista, el conjunto .message
de reglas se amplía con los otros dos conjuntos de reglas.
.message {
padding: 0.3em 0.5em;
border-radius: 0.5em;
}
.message-info {
@extend .message; 1
color: blue;
background-color: lightblue;
}
.message-danger {
@extend .message; 1
color: red;
background-color: pink;
}
Listado B.10. Ampliando una clase base
- Comparte estilos con la clase .message
Esto produce la siguiente salida:
.message,
.message-info,
.message-danger {
padding: 0.3em 0.5em;
border-radius: 0.5em;
}
.message-info {
color: blue;
background-color: lightblue;
}
.message-danger {
color: red;
background-color: pink;
}
Observe que Sass copió los selectores .message-info
y .message-danger
en el primer conjunto de reglas. El beneficio de esto es que su marcado solo necesita hacer referencia a una clase en lugar de dos: <div class="message message-info">
se convierte en <div class= "message-info">
porque la message-infoclase ahora también incluye todos los estilos para la messageclase, lo que hace que el uso de la messageclase sea redundante.
A diferencia de un mixin, @extend
mueve el selector a una ubicación anterior en la hoja de estilo. Esto significa que es posible que el orden de origen de sus declaraciones no coincida con el esperado, lo que puede afectar la cascada.
La longitud de la salida de @extend
es generalmente más corta que la de un mixin. Es fácil ver esto y pensar que es mejor porque la hoja de estilo resultante es más pequeña (y, por lo tanto, más rápida en la red). Pero es importante tener en cuenta que los mixins producen una gran cantidad de código repetido, y el código repetitivo se comprime muy bien cuando se comprime con gzip. Siempre que su servidor esté haciendo gzip en todo el tráfico de la red (lo que debería), estas ganancias suelen ser mucho menores de lo que cabría esperar.
No evite los mixins y utilícelos exclusivamente @extend
para proporcionar algún tipo de optimización del rendimiento. Considere la organización de su código y cuál, combinado o extendido, tiene más sentido de usar caso por caso. En general, probablemente deberías preferir los mixins. Úselo solo @extend
cuando desee acortar el número de nombres de clases necesarios en su HTML, como en el listado B.10.
Manipulación de color
Otra característica útil de Sass es una serie de funciones que le permiten manipular colores. Si necesita dos colores relacionados (por ejemplo, una versión más clara y más oscura del mismo verde), puede usar las funciones en la siguiente lista para producir los colores que necesita.
$green: #63a35c;
$green-dark: darken($green, 10%); 1
$green-light: lighten($green, 10%); 2
$green-vivid: saturate($green, 20%); 3
$green-dull: desaturate($green, 20%); 3
$purple: adjust-hue($green, 180deg); 4
$yellow: adjust-hue($green, -70deg); 4
$green-transparent: rgba($green, 0.5); 5
Listado B.11. Funciones de color Sass
- Se oscurece en un 10%
- Aclara en un 10%
- Ajusta la saturación del color
- Gira el tono alrededor de la rueda de colores.
- Ajusta la transparencia
Al usar estas funciones, puede editar el valor de una variable, pero permitir que el cambio afecte a otros colores relacionados. No tiene que almacenar el valor en una variable. Puede editarlo directamente en la propiedad donde lo necesite:
.page-header {
color: $green;
background-color: lighten($green, 50%);
}
Si necesita realizar manipulaciones más avanzadas, hay varias funciones de color más. Consulte https://jackiebalzer.com/color para obtener una referencia completa.
Bucles
Utilice bucles para iterar sobre un valor, produciendo ligeras variaciones. En el capítulo 15, utilicé varios :nth-child()
selectores para apuntar a elementos de menú consecutivos, dando a cada uno un poco diferente transition-delay
( listado 15.10). Este tipo de código se puede hacer de manera más sucinta con un bucle Sass, que usa una regla @for
arroba como se muestra en la siguiente lista.
@for $index from 2 to 5 { 1
.nav-links > li:nth-child(#{$index}) { 2
transition-delay: (0.1s * $index) – 0.1s; 3
}
}
s
Listado B.12. Iterando sobre una serie de valores
- Itera el valor del índice $ de 2 a 4
- Usa la variable en el selector
- Multiplica la variable por un valor de tiempo
Esto representa el mismo bloque de código varias veces, cada vez incrementando la variable $index
. Observe que usé la variable en el selector, escapándola con la notación #{}
. El código resultante se ve así:
.nav-links > li:nth-child(2) {
transition-delay: 0.1s;
}
.nav-links > li:nth-child(3) {
transition-delay: 0.2s;
}
.nav-links > li:nth-child(4) {
transition-delay: 0.3s;
}
En CSS simple, realizar cambios en este patrón puede resultar tedioso. Si decidiera incrementar el retardo de transición en 0,15 segundos, tendría que cambiar manualmente cada una de estas declaraciones a 0,15 segundos, 0,3 segundos y 0,45 segundos, sucesivamente. O, si quisiera agregar otra iteración, tendría que copiar manualmente un bloque y cambiar todos los valores. Pero con el ciclo Sass, estos cambios son una cuestión de editar la fórmula matemática o cambiar el recuento de iteraciones.
Es todo CSS
Los preprocesadores no cambian los fundamentos de CSS. Todo lo que cubrí en este libro todavía se aplica. No utilicé Sass en todo el libro porque quería dejar claro que los temas tratados son los elementos esenciales del lenguaje en sí, no de un preprocesador. Aún necesita comprender CSS para usar Sass. Pero Sass (o Less) puede eliminar gran parte del trabajo ocupado cuando se trabaja con CSS. Sass es una herramienta extremadamente útil. Te animo a que te familiarices con él.
B.2. PostCSS
PostCSS (https://postcss.org/) es un tipo diferente de preprocesador. Como Sass o Less, analiza un archivo fuente y genera un archivo CSS procesado. PostCSS, sin embargo, está completamente basado en complementos. Sin complementos, el archivo de salida sería una copia sin cambios del archivo de origen.
La funcionalidad que obtiene de PostCSS está totalmente determinada por los complementos que utiliza. Puede usar varios complementos que brinden la misma funcionalidad que Sass, o puede usar uno o dos complementos y ejecutar su código a través de Sass y PostCSS. Y, si lo desea, incluso puede escribir sus propios complementos en JavaScript.
Es importante tener en cuenta que PostCSS ejecuta complementos de forma secuencial. Si configura varios complementos, el orden en que se ejecutan es a veces significativo y puede ser necesario un poco de prueba y error para que PostCSS funcione de la manera deseada. Consulte la documentación de PostCSS para obtener ayuda con esta configuración.
Nota
Inicialmente, PostCSS se denominó posprocesador porque generalmente se ejecuta después del preprocesador. Sin embargo, PostCSS se ha alejado de este término en particular, ya que implica un alcance más limitado de todo lo que la herramienta puede ofrecer.
B.2.1. Usando Autoprefixer
Quizás el complemento más importante para PostCSS es Autoprefixer. Este complemento agrega todos los prefijos de proveedores apropiados a su CSS. Para obtener más información sobre los prefijos de proveedores, consulte la barra lateral "Prefijos de proveedores" en el capítulo 5.
Si su código fuente se ve así:
.example {
display: flex;
transition: all 0.5s;
background: linear-gradient(to bottom, white, black);
}
Autoprefixer agrega declaraciones adicionales, proporcionando alternativas con prefijos del proveedor a los navegadores más antiguos, y luego genera:
.example {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-transition: all .5s;
transition: all .5s;
background: -webkit-gradient(linear, left top, left bottom, from(white),
to(black));
background: linear-gradient(to bottom, white, black);
}
Si tuviera que escribir todos estos prefijos de proveedores a mano, sería tedioso y propenso a errores. También agrega mucho desorden a su código fuente en el que probablemente preferiría no tener que pensar cuando trabaja.
Puede configurar Autoprefixer con una lista de navegadores que desea admitir, y agregará prefijos de proveedores cuando sea necesario para admitir esos navegadores. Por ejemplo, configurarlo con la matriz ["ie >= 10", "last 2"]
garantiza que su código sea compatible (cuando sea posible) con IE10 y versiones posteriores, y las dos últimas versiones de todos los demás navegadores. Autoprefixer utiliza los datos más recientes de la base de datos caniuse.com para determinar cuándo se necesitan prefijos.
Le recomiendo encarecidamente que utilice Autoprefixer, incluso si no utiliza ningún otro complemento de PostCSS. A lo largo del libro, no incluyo prefijos de proveedores en mis ejemplos de código, suponiendo que usará Autoprefixer para hacer esto por usted.
B.2.2. Usando cssnext
Otro complemento popular de PostCSS (o más bien, un paquete de complementos) es cssnext (https://cssnext.io/). Estos complementos intentan emular sintaxis CSS futuras que aún no son compatibles con todos los navegadores (y algunas de las cuales no están finalizadas en la especificación CSS). En muchos sentidos, esto es como usar un polyfill para futuras funciones de CSS.
Muchas de las características de este complemento son similares a las proporcionadas por Sass: selectores de anidamiento, comportamiento similar al mixin usando una regla @apply
y funciones de manipulación de color. Autoprefixer también se incluye en este paquete. Consulte https://cssnext.io/features/ para obtener una lista completa de las funciones del complemento.
Tenga en cuenta que algunas de estas características aún se encuentran en las primeras etapas de desarrollo del W3C y es casi seguro que cambiarán antes de ser finalizadas. Utilice cssnext si desea familiarizarse con algunas funciones de CSS emergentes, pero no lo recomiendo como su único conjunto de reglas de preprocesador. Como los navegadores agregan soporte nativo para algunas de las características de cssnext, puede ser difícil pasar de procesarlas usando PostCSS a usarlas de forma nativa en el navegador; Es una buena idea mantener las reglas del preprocesador separadas de las reglas con relleno múltiple.
B.2.3. Usando cssnano
cssnano (https://cssnano.co/) es un minificador basado en PostCSS. Un minificador elimina todos los espacios en blanco extraños de su código y lo hace lo más pequeño posible, sin dejar de mantener el mismo significado sintáctico.
Nota
La minificación no reemplaza la compresión gzip, que debe aplicar su servidor. En general, es una buena práctica tanto minificar como gzip CSS para que la red acelere el tiempo de carga.
Hay varios minificadores de CSS disponibles, pero podría tener más sentido hacer esto como parte de su proceso de compilación de PostCSS, en lugar de en un paso separado. cssnano le permite hacer esto.
B.2.4. Usando PreCSS
PreCSS (https://github.com/jonathantneal/precss) es un paquete de complementos PostCSS que proporciona varias funciones similares a las de Sass. Esto incluye variables $
, cálculo en línea, bucles y mixins.
Si se siente ineficiente ejecutar su código a través de un preprocesador de Sass y PostCSS, considere reemplazar Sass con el paquete de complementos PreCSS para PostCSS. Sin embargo, no es perfectamente idéntico a Sass, así que consulte la documentación de PreCSS si elige seguir esta ruta. También es una herramienta más nueva y puede que no sea tan estable como Sass.