Windi CSS: El framework CSS de próxima generación

27 Enero, 2022 - 8 minutos de lectura

Windi CSS es un nuevo framework CSS basado en nombres de clases de utilidades, que incluye algunas características impresionantes, ofrece una experiencia de desarrollo ultra rápida, no usa ninguna dependencia (puedes usarlo sin instalar ninguna otra herramienta como PostCSS) y que además que se plantado como una gran alternativa al famoso Tailwind CSS.

Windi CSS: El framework CSS de próxima generación
Windi CSS: El framework CSS de próxima generación.

¿Cómo nació Windi CSS?

Windi CSS ha surgido por la antigua necesidad de hacer más rápida la experiencia de desarrollo que se tenía con Tailwind CSS, antes de que lanzaran la herramienta Just-in-Time (JIT) (que hace que las clases CSS que usemos en nuestro proyecto sean generadas bajo demanda), Tailwind siempre había sido criticado debido a los largos tiempos de ejecución al integrarlo en un proyecto, ya que se generaba un archivo CSS de gran tamaño con todas las clases incluyendo las que no hayamos definido.

Si bien quizás no conoces a Windi CSS, cabe destacar mencionar que JIT nació gracias a Windi CSS, y aunque se generó mucha polemica al respecto, Windi CSS nació gracias a Tailwind CSS, al final del día son herramientas que buscan ayudar a mejorar al desarrollo web en general y es desición tuya elegir cuál herramienta usar y que se adapte mejor a tu necesidades. En mi caso con Windi CSS he encontrado una herramienta fabulosa.

Windi CSS es un framework totalmente mantenido por una comunidad de desarrolladores apasionados con este proyecto y en el que cualquier desarrollador que lo desee puede aportar (y me emociona mencionar que yo también he aportado un poco, arreglando un pequeño problema que hacía imposible usar Windi CSS CLI y creando 2 plugins por el momento), mientras que Tailwind es un proyecto mantenido por una empresa (Tailwind Labs).

¿Cómo usar Windi CSS?

Podemos instalar e integrar Windi CSS con muchas herramientas como Vite, Webpack, Rollup, PostCSS, hacer uso de su CLI e incluso si quieres ir más allá de la CLI haz uso de su API de JavaScript, puedes utilizarlo con cualquier framework JavaScript como React, Vue, Svelte, etc. Además si ya tienes Tailwind CSS en tu proyecto también puedes migrar fácilmente a Windi.

Puedes darle un vistazo a su documentación para integrar Windi en tu proyecto:

Principales características de Windi CSS

Windi CSS es totalmente compatible con todas las características de Tailwind, por lo que no lo hecharás de menos. Entre las principales características que difieren un poco de Tailwind CSS están:

Valores autogenerados

¿Haz escuchado sobre los valores arbitrarios de Tailwind?, pues bien, en Windi CSS también puedes usarlos ya que todas las clases son autogeneradas.

<!-- Tamaños y posiciones -->
<div class="p-5px mt-[0.3px]"></div>
<div class="pt-1.4rem pb-[1.2rem] mx-12px"></div>
<div class="w-9/12"></div>

<!-- Colores -->
<button class="bg-hex-b2a8bb"></button>
<button class="bg-[#b2a8bb]"></button>
<button class="bg-[hsl(211.7,81.9%,69.6%)]"></button>

<!-- Valores autogenerados para CSS Grid -->
<div class="grid-cols-[auto,1fr,30px]"></div>

Como podrás notar puedes usar la sintaxis de corchetes para indicar explicitamente el valor mt-[0.3px] o aplicar el valor directamente pt-1.4rem, incluso utilizando valores de fracciones como w-9/12.

También puedes pasar variables como valores:

<div class="bg-$variable"></div>

Lo que generará el siguiente código en CSS:

.bg-\$variable {
  background-color: var(--variable);
}

Grupos de variantes

Aplicar variantes de estado como hover: para múltiples utilidades es algo muy tedioso:

<a
  class="hover:bg-blue-500 hover:underline hover:font-semibold text-white font-light"
></a>

En Windi tienes la opción de agrupar las utilidades para las variantes de estado de la siguiente manera:

<a
  class="hover:(bg-blue-500 underline font-semibold) text-white font-light"
></a>

Variantes responsive

Además de usar de forma predeterminada el patrón de diseño responsive Mobile First, en Windi también podemos utilizar el patrón Desktop First y establecer estilos en un rango determinado sin ningún tipo de configuración extra:

<!-- Mobile First -->
<div class="bg-blue-100 sm:bg-blue-500"></div>

<!-- Desktop First -->
<div class="bg-blue-500 <md:bg-blue-100"></div>

<!-- Rango para tamaño sm -->
<div class="bg-blue-100 @sm:bg-blue-500"></div>

Siendo el CSS generado:

/* Mobile First */
.bg-blue-100 {
  --tw-bg-opacity: 1;
  background-color: rgba(219, 234, 254, var(--tw-bg-opacity));
}

@media (min-width: 640px) {
  .sm\:bg-blue-500 {
    --tw-bg-opacity: 1;
    background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
  }
}

/* Desktop First */
.bg-blue-100 {
  --tw-bg-opacity: 1;
  background-color: rgba(219, 234, 254, var(--tw-bg-opacity));
}

@media (max-width: 767.9px) {
  .\<md\:bg-blue-100 {
    --tw-bg-opacity: 1;
    background-color: rgba(219, 234, 254, var(--tw-bg-opacity));
  }
}

/* Rango para tamaño sm */
.bg-blue-100 {
  --tw-bg-opacity: 1;
  background-color: rgba(219, 234, 254, var(--tw-bg-opacity));
}

@media (min-width: 640px) and (max-width: 767.9px) {
  .\@sm\:bg-blue-500 {
    --tw-bg-opacity: 1;
    background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
  }
}

Agrupar variantes responsive

Al igual que podemos agrupar variantes de estado, también podemos agrupar las variantes responsive.

<div class="block md:flex md:items-center md:flex-col"></div>

A la forma agrupada:

<div class="block md:(flex items-center flex-col)"><div></div></div>

Configurar alias

Así como en Tailwind podemos configurar reutilizar clases, en Windi existen los shortcuts, pero existe una característica aún más interesante y son los alias.

Diferencia entre los shortcuts y los alias

La forma en que funcionan los shortcuts, es que estos crean una clase por separado para cada atajo que apliquemos, por ejemplo:

module.exports = {
  // ...
  shortcuts: {
    'btn-blue':
      'px-4 py-1 text-sm text-blue-600 font-semibold rounded-full border border-blue-200 hover:text-white hover:bg-blue-600',
    'btn-purple':
      'px-4 py-1 text-sm text-purple-600 font-semibold rounded-full border border-purple-200 hover:text-white hover:bg-purple-600'
  }
  // ...
}

Al utilizar el shortcut, puedes llamar directamente el nombre de la clase, ya que esta es generada:

<button class="btn-blue"></button> <button class="btn-purple"></button>

Pero al configurar los alias es diferente, ya que reemplazan el texto por las utilidades que le hayamos definido, con la limitancia que no podemos utilizar CSS anidado complejo:

module.exports = {
  // ...
  alias: {
    'btn-blue': 'px-4 py-1 text-sm text-blue-600 font-semibold',
    'btn-purple': 'px-4 py-1 text-sm text-purple-600 font-semibold'
  }
  // ...
}

Y para utilizar el alias en nuestro código HTML, debemos añadir el símbolo * antes del nombre, para indicarle a Windi CSS que es un alias propiamente, de la siguiente manera:

<button class="*btn-blue"></button> <button class="*btn-purple"></button>

Lo que sería equivalente a:

<button class="px-4 py-1 text-sm text-blue-600 font-semibold"></button>
<button class="px-4 py-1 text-sm text-purple-600 font-semibold"></button>

Para conocer más sobre los alias lee la publicación sobre las novedades de la tercera versión de Windi CSS en su documentación.

Modo Attributify

Una forma muy elegante que podemos utilizar en Windi es estilizar los elementos en HTML con atributos 🤯.

Por defecto el modo attributify es opcional, para activarlo añadimos la propiedad attributify en true en nuestro archivo de configuración:

module.exports = {
  // ...
  attributify: true
  // ...
}

Existen 2 formas de utilizar el modo attributify, haciendo uso de atributos de utilidades y usando atributos de variantes. Aunque puedes combinar ambos paradigmas, no es recomendable, para mantener la coherencia o consistencia en tus estilos, así que debes elegir el que más te convenga.

Modo attributify utilizando utilidades

<button
  bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
  text="sm white"
  font="mono light"
  p="y-2 x-4"
  border="2 rounded blue-200"
>
  Botón
</button>

Modo attributify utilizando variantes

<button
  sm="bg-blue-200 hover:bg-blue-300"
  sm:hover="bg-blue-200 dark:bg-blue-300"
>
  Botón
</button>

Obviamente podemos seguir utilizando el atributo class en ambos casos.

Añadir un prefijo personalizado

Si deseamos añadir un prefijo personalizado para los atributos, debemos configurarlo de la siguiente manera:

module.exports = {
  // ...
  attributify: {
    prefix: 'w:'
  }
  // ...
}

Y lo usamos en nuestro código HTML:

<button
  w:bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
  w:text="sm white"
  w:font="mono light"
  w:p="y-2 x-4"
  w:border="2 rounded blue-200"
>
  Botón
</button>

Para conocer todos los atributos disponibles dale un vistazo a la refencia del modo attributify.

Modo Interpretado y Modo Compilado

En Windi CSS podemos generar clases de 2 formas diferentes.

Modo Interpretado

El modo interpretado es el utilizado por defecto, donde establecemos todas las clases que necesitemos en nuestros documentos y este se encargará de escanearlas y generar el CSS apropiado para cada utilidad que hayamos definido.

<div class="bg-white block sm:flex sm:flex-shrink-0"></div>

Generará el siguiente CSS:

.bg-white {
  --tw-bg-opacity: 1;
  background-color: rgba(255, 255, 255, var(--tw-bg-opacity));
}

.block {
  display: block;
}

@media (min-width: 640px) {
  .sm\:flex {
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
  }
  .sm\:flex-shrink-0 {
    -ms-flex-negative: 0;
    -webkit-flex-shrink: 0;
    flex-shrink: 0;
  }
}

Modo Compilado

En cuánto al modo compilado, este se encarga sintetizar o unificar todas las clases que hayamos utilizado en cada etiqueta HTML de nuestro proyecto a una sola, por ejemplo:

<div class="bg-white rounded-xl shadow-md mx-auto max-w-sm px-8 py-8"></div>

Al ejecutar el modo compilado se analizarán las clases y generará un nuevo archivo HTML con la siguiente nombre de clase CSS similar a este:

<div class="windi-15wa4me"></div>

Y el nuevo código CSS generado:

.windi-15wa4me {
  --tw-bg-opacity: 1; /* bg-white */
  --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */
  -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(
      --tw-ring-shadow,
      0 0 #0000
    ), var(--tw-shadow); /* shadow-md */
  background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); /* bg-white */
  border-radius: 0.75rem; /* rounded-xl */
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(
      --tw-ring-shadow,
      0 0 #0000
    ), var(--tw-shadow); /* shadow-md */
  margin-left: auto; /* mx-auto */
  margin-right: auto; /* mx-auto */
  max-width: 24rem; /* max-w-sm */
  padding-left: 2rem; /* px-8 */
  padding-right: 2rem; /* px-8 */
  padding-top: 2rem; /* py-8 */
  padding-bottom: 2rem; /* py-8 */
}

¿Cómo usar el Modo Compilado?

La forma más fácil de utilizar del modo compilado es hacer uso de la CLI de Windi. Para ello crearemos un proyecto de prueba haciendo uso del siguiente comando:

npx windicss --init winditest

Esto generará una carpeta llamada winditest y dentro habrán 2 archivos, index.html y windi.css. Para hacer uso del modo compilado ahora vamos a ejecutar el siguiente comando ubicándonos dentro de la carpeta:

npx windicss 'index.html' -ct

Esto creará un nuevo archivo index.windi.html y reemplazará los estilos en windi.css con las nuevas clases creadas. Si quieres evitar reemplazar los estilos en el archivo windi.css, simplemente ejecuta el siguiente comando para crear otro archivo CSS:

npx windicss 'index.html' -cto windi.compiled.css

Para conocer más visita la refencia sobre la CLI de Windi CSS.

Analizador virtual de clases

El analizador virtual de clases, es una herramienta para Windi CSS, en la que permite visualizar todas las utilidades y colores que hemos utilizado en nuestro proyecto. Para hacer uso de esta herramienta ejecutamos el comando:

npx windicss-analysis

Y esto creará un servidor en el que podemos acceder a través de nuestro navegador en la dirección: http://localhost:8113. Verás algo similar a esto:

Algunas utilidades y colores utilizados en mi sitio web felixicaza.com
Algunas utilidades y colores utilizados en mi sitio web.

Conoce más sobre la herramienta Analizador de clases de Windi.

Diseño en las herramientas de desarrollo

Así como podemos usar Tailwind desde una CDN, en Windi CSS no es la excepción y además incluye la característica de que podemos añadir clases directamente desde las herramientas de desarrollo de nuestro navegador y estas serán actualizadas instantáneamente, sin ningún tipo de configuración ni realizar ninguna compilación extra 👏🎉.

Puedes añadir clases desde las herramientas de desarrollo y estas se verán actualizadas instantáneamente.

¿Cómo añadir Windi CSS Runtime DOM?

Para añadir Windi CSS Runtime DOM, simplemente debes agregar una etiqueta <script> a tu archivo HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://unpkg.com/windicss-runtime-dom"></script>
  </head>
  <body class="block" hidden>
    <h1 class="font-bold text-3xl underline">¡Windi CSS Runtime DOM!</h1>
  </body>
</html>

Es importante añadir el atributo hidden y la clase block a la etiqueta body para prevenir FLOUC (flash de contenido sin estilo, por sus siglas en inglés) y ¡listo!.

Añadiendo configuraciones

Para configurar algunas opciones de la librería, debes añadir otra etiqueta <script> y llamar al objeto windicssRuntimeOptions:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script>
      window.windicssRuntimeOptions = {
        // Habilitar preflight
        preflight: true,
        // Escanear todo el DOM para generar los nombres de clase en la página
        extractInitial: true,
        // Generar clases simuladas para que el navegador haga el autocompletado
        mockClasses: false,
        // La añade configuraciones de Windi `windi.config.js`
        config: {}
      }
    </script>
    <script src="https://unpkg.com/windicss-runtime-dom"></script>
  </head>
  <body class="block" hidden>
    <h1 class="font-bold text-3xl underline">¡Windi CSS Runtime DOM!</h1>
  </body>
</html>

Para conocer más sobre Windi CSS Runtime DOM visita su repositorio de GitHub: https://github.com/antfu/windicss-runtime-dom.

Algunos plugins interesantes

Algunos plugins que te encantará agregar a tu proyecto con Windi, son:

  • Animations: Se encarga de utilizar la famosa librería de animaciones Animate.css, para que añadamos animaciones fácilmente con Windi.
  • Scrollbar: Personaliza la barra de scroll para navegadores basados en WebKit y Firefox.
  • Question mark: Es un plugin útil para depurar cualquier elemento HTML.
  • Heropatterns: Hero Patterns, es un sitio web que incluye una gran cantidad de patrones, mediante este plugin podemos utilizarlos en nuestro proyecto.

Este ha sido un repaso a las funcionalidades que a mi parecer son muy destacadas de Windi CSS. Si quieres conocer más sobre este proyecto visita su sitio web: https://windicss.org/, o su repositorio de GitHub: https://github.com/windicss/windicss/.

Lo que más me emociona acerca de Windi CSS, es que es un proyecto totalmente mantenido por la comunidad, y que, comparado con Tailwind es mucho más flexible en muchos casos como lo puedes comprobar en las características ya mencionadas es este artículo, ya que Windi tiene un motor hecho enteramente con TypeScript y no depende de herramientas de terceros como PostCSS en el caso Tailwind CSS. A pesar de que no es muy conocido poco a poco ha madurardo como proyecto y seguramente seguirá innovando para mejorar la experiencia de desarrollo a otro nivel.

Referencia:


Si te ha gustado este artículo, podrías invitarme a un café, te lo agradecería muchísimo.

Invítame a un café

¡Comparte este artículo!

Otras publicaciones

Mira otras publicaciones