CSS Modules: Estilos modulares

Creando módulos de CSS preprocesados


Una opción muy utilizada en el ecosistema de CSS-in-JS es la conocida por CSS Modules. No se trata de una librería ni un framework, sino una estrategia con la que podemos conseguir varias cosas:

  • 1️⃣ Dividir en ficheros .module.css separados (módulos de CSS)
  • 2️⃣ Conseguir «scope» local para cada módulo (evitar colisiones)
  • 3️⃣ Código más fácil de mantener y escalar

Con estas ventajas, trabajar en una aplicación web con CSS se hace mucho más sencillo. Veamos que pasos podemos seguir para poder trabajar de esta forma.

Instalación

Al no ser una librería ni framework, sino una estrategia, podemos trabajar de múltiples formas, y simplemente adoptar CSS modules como enfoque complementario. Si utilizamos Vite es muy sencillo, ya que tiene integración incorporada.

Uso

Utilizar CSS Módules es muy sencillo. Se basa en crear pequeños ficheros llamados módulos CSS con la extensión .module.css. Esto hará que nuestro proyecto identifique si se trata de un .css normal o un fichero módulo CSS.

Al importarlo, Javascript nos devuelve un objeto con las clases de ese módulo CSS, que tendremos que asignar a la clase del elemento HTML. Veamos un ejemplo:

/* component.module.css */

.title {
  background: indigo;
  color: white;
  padding: 1rem;
}

.warning {
  background: darkred;
}

Observa que cuando importamos el fichero .module.css con Vite, se carga ese fichero como un módulo CSS y se devuelve un objeto con las clases del módulo y la clase autogenerada por CSS módulos, para hacer la clase única y evitar colisiones de nombres de clases. Luego, a la hora de trabajar con estos estilos lo haremos de la siguiente forma:

import classes from "./component.module.css";

/*
classes = {
  title: "title_13rzd_1",
  warning: "warning_1csbp_8"
}
*/

const element = document.querySelector(".element");

element.classList.add(classes.title);
element.textContent = "Hello world! Styled with CSS Modules";

Esto puede ser una forma más controlada de usar CSS con un enfoque local, que puede ser interesante para utilizar en aplicaciones web. Además, recuerda que podemos utilizar CSS Nesting para dar estilo a elementos que estén incluidos en el elemento o componente.

Composición en CSS Modules

Además, CSS Modules tiene algunas características interesantes como la composición mediante la propiedad composes. Esta propiedad no existe en CSS nativo, pero CSS Modules la añade para poder trabajar heredando estilos.

Veamos un ejemplo:

.coreTitle {
  background: indigo;
  color: white;
  padding: 1rem;
}

.warningTitle {
  composes: coreTitle;
  background: darkred;
}

Observa que estamos creando una clase warningTitle que usa composición para heredar todo lo que tiene coreTitle. Se trata de una especie de mixin muy interesante para reutilizar estilos.

Personalización de clases

En algunos casos puede que no estemos conforme con el nombre de clases que genera CSS Modules. Esto es personalizable, editando el fichero vite.config.js de nuestro proyecto:

export default {
  css: {
    modules: {
      generateScopedName: 'manzdev-[name]__[local]___[hash:base64:5]'
    }
  }
}

Utilizamos:

  • [name] para indicar el nombre del fichero original
  • [local] para indicar el nombre de la clase original
  • [hash:base64:5] para generar un hash de 5 carácteres en Base64.
  • Podemos usar otras configuraciones como [ext], [path], [folder] o [query], o configurar el hash con sha1, md5, sha512, etc. Tienes más información en opciones del hash.

Ten en cuenta, que por defecto CSS modules se procesa mediante PostCSS. También es posible configurarlo con LightningCSS, donde las opciones anteriores no tendrían efecto. En ese caso, se configuraría así:

export default {
  css: {
    lightningcss: {
      cssModules: true
    }
  }
}

Si buscas una forma estándar y nativa de utilizar CSS Modules, sin necesidad de preprocesadores, te recomiendo echar un vistazo a CSSStyleSheet, donde lo explico en detalle.

¿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