Vanilla Extract: CSS-in-JS en objetos

Librería CSS-in-JS basada en objetos Javascript


Dentro del ecosistema de CSS-in-JS, una de las librerías más populares es Vanilla Extract. Entre las ventajas de esta solución están las siguientes:

  • Estilos generados de forma estática (como Sass) pero con los beneficios de Typescript.
  • Posibilidad de crear temas con tokens tipados, con autocompletado, etc.
  • Agnóstico al framework. Puedes usarlo con React, Webpack, Vite, NextJS, etc.

Instalación

La instalación de Vanilla Extract es muy sencilla. Básicamente, se trata de instalar dos paquetes: el primero @vanilla-extract/css que es el core que se necesita para utilizar la librería, y @vanilla-extract/vite-plugin que es el plugin que permite integrar la librería con Vite. Esas instalaciones las hacemos desde una terminal así:

$ npm install -D @vanilla-extract/css @vanilla-extract/vite-plugin

Si queremos utilizar otra herramienta en lugar de Vite, en su documentación oficial tienes otras integraciones. En el caso de Vite, debemos ir a nuestro fichero vite.config.js y escribir lo siguiente:

import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';

export default {
  plugins: [vanillaExtractPlugin()]
};

Con esto estaremos listos para comenzar a usar la librería.

Uso de la librería

Como hemos mencionado anteriormente, CSS-in-JS es una forma de utilizar CSS dentro de nuestros ficheros Javascript. En este caso, casi hablamos de CSS-in-TS, ya que se aprovechan algunos de los beneficios de Typescript. Para utilizar Vanilla Extract, creamos un fichero component.css.ts con el siguiente contenido:

/* component.css.ts */
import { style } from '@vanilla-extract/css';

export const styles = style({
  display: "flex",
  backgroundColor: "indigo",
  color: "white",
  padding: "1rem" // Si se añade como número, se asume que son "px"
});
/* component.ts */
import { styles } from "./components/component.css.ts";

const component = document.createElement("div");
component.textContent = "Contenido de texto";
component.classList.add(styles);
document.body.append(component);

Este es el fichero que contiene los estilos CSS en forma de objeto de Javascript, de forma muy similar a los módulos CSS, ya que sólo tenemos que añadir la clase que nos devuelve en styles al elemento HTML.

Observa que las propiedades del objeto son las propiedades CSS, pasadas del formato kebab-case a camelCase, que es más apropiado para Javascript. En algunos casos, como variables CSS, pseudoclases u otros, debemos crear objetos anidados:

import { style } from '@vanilla-extract/css';

const base = style({
  padding: 12
});

export const styles = style([base, {
  display: "flex",
  ":hover": {
    backgroundColor: "deeppink"
  },
  "::before": {
    content: ""
  },
  "@media": {
    "(width <= 800px)": {
      backgroundColor: "red"
    }
  }
}]);

Al estar trabajando con Typescript, estaremos aprovechando las características de tipado que tiene, así como los beneficios del autocompletado, por lo que tras escribir los : podemos pulsar CTRL+ESPACIO para ver las opciones disponibles.

Además, observa que en este caso hemos creado dos objetos, y en el segundo de ellos, utilizamos un array para utilizar composición y fusionar los estilos de cada uno.

Creación de temas

Otro detalle muy interesante de Vanilla Extract es la posibilidad de crear temas. Para ello, creamos un objeto utilizando la función createTheme(), pasándole también un objeto:

import { createTheme } from "vanilla-extract/css";

export const [themeClass, vars] = createTheme({
  color: {
    brand: "blue"                 // --color-brand__[hash]: blue
  },
  font: {
    body: "arial, sans-serif"     // --font-body__[hash]: arial, sans-serif;
  }
});

Con la información de este objeto se crearán variables CSS para utilizar como tema. Observa que las propiedades del objeto mencionado son el namespace (la primera parte) de la variable CSS, mientras que se continua la variable CSS con los nombres de las propiedades del objeto de su interior.

La ventaja principal de crear estos objetos (y no una variable CSS directamente) es que podremos aprovechar el autocompletado de nuestro editor para completar estos nombres de temas y utilizarlas con seguridad en el resto de nuestra aplicación.

Alternativas a Vanilla Extract

Existen muchas otras librerías CSS-in-JS alternativas que permiten trabajar con objetos Javascript (o de forma muy similar). Veamos algunas de ellas:

LibreríaGenera CSS estáticoSintaxis de objetosSintaxis de templatesGitHub
Vanilla ExtractGitHub
Panda CSSGitHub
ECCStaticGitHub
LinariaGitHub
EmotionGitHub
Styled ComponentsGitHub
Stitches DeprecatedGitHub

Si no lo has visto aún, echa un vistazo a ECSStatic, un post donde vemos una librería CSS-in-JS con sintaxis de string templates.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev