Tailwind CSS v4: El Futuro es CSS-First (¡y te muestro cómo configurarlo!)

DUGLAS MORENODUGLAS MORENO 👁 6

¿Qué onda con Tailwind CSS v4 y el Enfoque CSS-First?

¡Che, qué bueno que te sumás a esta movida! Si estás metido en el desarrollo frontend, seguramente ya conocés o, por lo menos, escuchaste hablar de Tailwind CSS. Es esa librería utilitaria que nos cambió la forma de encarar los estilos, permitiéndonos construir interfaces complejas directamente desde nuestro HTML con clases como flex, pt-4, text-center, etc. La velocidad de desarrollo que te da es una locura, ¿viste?

Pero como todo en el mundo tech, la cosa evoluciona. Y ahora, con la versión 4 de Tailwind CSS (que al momento de escribir esto está en su fase next/RC), los muchachos de Tailwind Labs nos traen un cambio significativo: el enfoque CSS-First. ¿Qué significa esto? Bueno, si antes el tailwind.config.js era el rey de la configuración y PostCSS era el cerebro detrás de la magia, ahora la onda es un poco distinta y, te diría, mucho más directa y eficiente.

¿Cuál es el problema que viene a solucionar Tailwind v4?

Las versiones anteriores de Tailwind, si bien eran geniales, tenían algunos "peros":

  • Dependencia de PostCSS para todo el core: Si bien PostCSS es una herramienta fantástica, requería que todo el proceso de build de Tailwind pasara por él, incluso para las configuraciones más básicas. Esto sumaba un paso y, a veces, una capa de abstracción que podía ser innecesaria.
  • Bundle size del runtime: Aunque Tailwind es excelente optimizando el CSS final en producción (purga lo que no usás), el motor de ejecución en desarrollo no siempre era el más liviano.
  • Configuración en JS para todo: Querer definir un color nuevo o un tamaño de fuente implicaba meter mano en el tailwind.config.js. Si bien está bien para configuraciones globales, a veces uno quiere hacer cosas más rápidas y contextuales.

¿Para quién es este tutorial?

Este artículo es para vos si:

  • Ya usás Tailwind CSS y querés entender las novedades de la v4.
  • Estás pensando en sumarte al mundo de Tailwind y querés empezar con el pie derecho, con la última versión.
  • Sos un desarrollador frontend que busca optimizar su flujo de trabajo y el rendimiento de sus aplicaciones.

¿Qué vas a aprender hoy?

Vamos a meternos de lleno en cómo configurar un proyecto desde cero usando Tailwind CSS v4 con su flamante enfoque CSS-First. Vas a ver:

  • Las diferencias clave de la v4.
  • Cómo instalarla y preparar tu entorno.
  • La nueva forma de configurar tu tema directamente en un archivo CSS.
  • Cómo compilar tu CSS y usarlo en un proyecto HTML simple.
  • Algunas buenas prácticas y los errores más comunes para que no te agarre desprevenido.

¡Preparate para que tu flujo de desarrollo de CSS sea todavía más rápido y divertido!

Entendiendo la Configuración CSS-First en Tailwind v4

El nombre lo dice todo: CSS-First. Esto significa que tu archivo input.css (o como le quieras llamar a tu CSS de entrada) ahora no es solo un importador de las directivas @tailwind, sino que se convierte en el centro de tu configuración de diseño. ¿Te acordás que antes tenías que ir al tailwind.config.js para modificar los colores, las fuentes o el espaciado? Bueno, ahora muchas de esas cosas las podés definir directamente en tu CSS, usando unas nuevas directivas.

El rol de @theme y @config

En Tailwind v4, se introducen dos nuevas directivas CSS que son clave:

  • @theme: Esta directiva te permite definir tokens de diseño (colores, tipografías, espaciados, etc.) directamente en tu CSS. Es como tener una parte del tailwind.config.js migrada al CSS, lo que simplifica mucho la gestión de tu sistema de diseño.
  • @config: Esta directiva, por otro lado, es para apuntar a un archivo tailwind.config.js externo. ¿Por qué sigue existiendo? Porque el tailwind.config.js aún es necesario para cosas más avanzadas, como plugins personalizados, presets, o si tenés configuraciones muy complejas que preferís mantener en JavaScript. Para la mayoría de los casos de uso, especialmente al principio, tu tailwind.config.js puede ser muy minimalista, o incluso no existir si solo usás @theme.

El gran objetivo de este cambio es que Tailwind v4 sea más rápido, más liviano y que te dé una experiencia de desarrollo más fluida, reduciendo la necesidad de un runtime de JavaScript pesado y moviendo el parsing y la configuración a un proceso de build de CSS más nativo.

Preparando el Terreno: Iniciando un Proyecto desde Cero

Para arrancar, vamos a crear un proyecto HTML súper básico. Esto nos va a servir de base para ver cómo integrar Tailwind CSS v4.

1. Creando la Carpeta del Proyecto y el package.json

Primero, creá una carpeta para tu proyecto y, dentro de ella, inicializá un proyecto de Node.js. Esto nos va a generar el package.json donde vamos a guardar nuestras dependencias.

mkdir tailwind-v4-css-first
cd tailwind-v4-css-first
npm init -y

La salida esperada de npm init -y debería ser algo así:

{
  "name": "tailwind-v4-css-first",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

2. Estructura de Archivos Básica

Ahora, vamos a armar una estructura de carpetas simple. Vas a necesitar un archivo HTML para ver tus estilos, y una carpeta para tus archivos CSS.

mkdir src dist
touch index.html src/input.css

Tu estructura de proyecto debería verse así:

tailwind-v4-css-first/
├── node_modules/
├── src/
│   └── input.css
├── dist/
├── index.html
└── package.json

3. Contenido Inicial de index.html

Para que tengamos algo que mostrar, agregá este HTML básico a tu archivo index.html:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tailwind CSS v4 CSS-First</title>
    <!-- Acá vamos a linkear nuestro CSS compilado -->
    <link rel="stylesheet" href="./dist/output.css">
</head>
<body>
    <div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4 mt-10">
        <div class="shrink-0">
            <!-- Placeholder para un logo o icono -->
            <svg class="h-12 w-12 text-blue-500" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm-.001 3a7 7 0 1 0 .002 14A7 7 0 0 0 12 5zm-.001 2a5 5 0 1 1 .002 10A5 5 0 0 1 12 7zm-.001 2a3 3 0 1 0 .002 6A3 3 0 0 0 12 9z"/></svg>
        </div>
        <div>
            <div class="text-xl font-medium text-black">¡Hola Mundo!</div>
            <p class="text-slate-500">Esto es Tailwind CSS v4 con CSS-First.</p>
        </div>
    </div>

    <div class="mt-8 text-center">
        <button class="bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded-full">
            Haceme click
        </button>
    </div>
</body>
</html>

Por ahora, si abrís index.html en tu navegador, vas a ver texto plano sin estilos, porque todavía no generamos output.css.

Instalando Tailwind CSS v4 y sus Dependencias

Ahora viene lo importante: instalar Tailwind CSS v4. Recordá que, al ser una versión next/RC, se instala con la etiqueta @next.

npm install -D tailwindcss@next postcss

¿Por qué postcss? Si bien Tailwind v4 ya no requiere PostCSS para su motor interno de compilación (ahora lo hace de forma nativa), PostCSS sigue siendo una herramienta estándar en el ecosistema de build de CSS. Muchas herramientas de frontend (como Vite, Webpack, Parcel) usan PostCSS para integrar plugins, autoprefijos, y para manejar el pipeline de CSS en general. Así que, para una compatibilidad amplia y para casos donde quieras agregar más plugins de PostCSS, es buena práctica tenerlo instalado.

La salida de la instalación debería ser algo parecido a esto (las versiones pueden variar un poco):

added 2 packages in 1s

Verificá que en tu package.json aparezcan las dependencias:

{
  "name": "tailwind-v4-css-first",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "postcss": "^8.4.X",
    "tailwindcss": "^4.0.0-next.X"
  }
}

Creando tu Archivo de Configuración de Tailwind (el CSS-First Way)

Llegó el momento de meter mano en src/input.css. Este archivo es ahora el corazón de tu configuración de Tailwind v4. Vamos a incluir las directivas @tailwind de siempre, y las nuevas directivas @theme para definir nuestros tokens de diseño.

Abrí src/input.css y pegá lo siguiente:

/* src/input.css */

/* 
  La directiva @config es opcional si no tenés un tailwind.config.js
  o si solo usás las configuraciones por defecto. 
  Acá, lo vamos a dejar para mostrar cómo se enlaza a un archivo JS si fuera necesario.
*/
@config "./tailwind.config.js";

@tailwind base;
@tailwind utilities;

/* 
  ¡Acá empieza la magia del CSS-First! 
  Usamos @theme para extender o reemplazar el tema por defecto de Tailwind.
*/
@theme {
  colors: {
    // Extiende la paleta de colores por defecto de Tailwind
    'blue': {
      50: '#eff6ff',
      100: '#dbeafe',
      200: '#bfdbfe',
      300: '#93c5fd',
      400: '#60a5fa',
      500: '#3b82f6',
      600: '#2563eb',
      700: '#1d4ed8',
      800: '#1e40af',
      900: '#1e3a8a',
      950: '#172554',
    },
    // Podés definir tus propios colores personalizados
    'violet': {
      DEFAULT: '#8b5cf6', // Color por defecto para 'bg-violet'
      light: '#c4b5fd',
      dark: '#7c3aed',
      600: '#7c3aed', // Agregamos un tono específico para el botón de ejemplo
      700: '#6d28d9'
    },
    'custom-green': '#10B981',
    'black': '#000000', // Definimos el color negro explícitamente
    'white': '#ffffff', // Y el blanco
    'slate': {
      50: '#f8fafc',
      100: '#f1f5f9',
      200: '#e2e8f0',
      300: '#cbd5e1',
      400: '#94a3b8',
      500: '#64748b',
      600: '#475569',
      700: '#334155',
      800: '#1e293b',
      900: '#0f172a'
    }
  };

  font-family: {
    // Agrega una fuente personalizada
    'sans': ['Inter', 'sans-serif'],
    'mono': ['Space Mono', 'monospace'],
  };

  extend: {
    spacing: {
      // Agrega un espaciado personalizado
      '128': '32rem',
      '144': '36rem',
    };
  };
};

/* 
  Acá podrías agregar tus propias reglas CSS si lo necesitás,
  fuera de las directivas de Tailwind.
*/
body {
  font-family: 'Inter', sans-serif;
  background-color: #f0f2f5;
}

¡Ojo! En el ejemplo anterior, estamos usando @config "./tailwind.config.js";. Esto implica que tenemos que crear ese archivo, incluso si está vacío, para que no falle. Para este tutorial, podés crearlo así:

touch tailwind.config.js

Y dejalo vacío o con un objeto básico, como este:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,html}'], // Asegurate de que el 'content' apunte a tus archivos donde usás clases de Tailwind
  theme: {},
  plugins: [],
}

La directiva @theme es muy flexible. Podés:

  • Extender el tema por defecto: Por ejemplo, colors: { extend: { 'nueva-onda': '#ff00ff' } }.
  • Sobrescribir secciones enteras: Como hicimos con colors arriba, donde definimos blue y violet con sus propios tonos.
  • Agregar nuevas secciones: Si necesitás algo totalmente nuevo. Pero para el theme de Tailwind, las secciones colors, spacing, fontFamily, fontSize, etc. ya están predefinidas.

Construyendo tu CSS con el CLI de Tailwind v4

Con todo configurado, ahora vamos a generar nuestro archivo output.css. Para esto, vamos a usar el comando de línea de interfaz (CLI) de Tailwind CSS directamente. Es la forma más sencilla de compilar tu CSS sin integrar herramientas de build más complejas por ahora.

1. Compilación Inicial

Ejecutá el siguiente comando en tu terminal:

npx tailwindcss -i ./src/input.css -o ./dist/output.css
  • -i ./src/input.css: Le dice a Tailwind dónde está tu archivo de entrada (input CSS).
  • -o ./dist/output.css: Le indica dónde tiene que guardar el archivo CSS compilado.

La salida esperada no suele ser muy verbosa, simplemente te devolverá al prompt de la terminal si todo salió bien. Sin embargo, en algunas versiones de desarrollo, podría mostrarte qué archivos procesó.

Después de ejecutarlo, si revisás la carpeta dist, vas a encontrar un archivo output.css generado. ¡Abrilo! Vas a ver un montón de clases utilitarias de Tailwind, incluyendo los colores personalizados y otras configuraciones que definiste en src/input.css.

2. Modo "Watch" para Desarrollo

Durante el desarrollo, no querés estar ejecutando el comando de compilación cada vez que hacés un cambio, ¿no? Para eso, usamos el modo --watch.

npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch

Este comando va a dejar el proceso corriendo en tu terminal, observando cualquier cambio en src/input.css (o en tus archivos HTML donde usás las clases de Tailwind, gracias a la configuración content en tailwind.config.js) y recompilando automáticamente el output.css cada vez que detecte una modificación.

La salida te indicará que está en modo "watch":

watching for changes...

Ahora, abrí index.html en tu navegador. ¡Deberías ver los estilos de Tailwind aplicados! La tarjeta max-w-sm con sombra y bordes redondeados, los textos con sus colores y tamaños, y el botón con los colores violeta que definimos en @theme.

Si abrís las herramientas de desarrollador de tu navegador y revisás el CSS, vas a notar que el CSS generado es bastante compacto y solo contiene las utilidades que realmente estás usando en tu HTML. ¡Esa es la magia de Tailwind!

Usando Tailwind v4 en tu HTML: Un Ejemplo Práctico

Ya lo viste en el index.html de ejemplo, pero vamos a repasar cómo se ve la integración. Con la versión 4, el uso de las clases utilitarias en tu HTML sigue siendo exactamente el mismo. No hay cambios ahí, y esa es una de las grandes ventajas: la sintaxis de las clases es estable.

Volvamos a nuestro index.html y analicemos un poco las clases que usamos:

    <div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4 mt-10">
        <div class="shrink-0">
            <svg class="h-12 w-12 text-blue-500" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm-.001 3a7 7 0 1 0 .002 14A7 7 0 0 0 12 5zm-.001 2a5 5 0 1 1 .002 10A5 5 0 0 1 12 7zm-.001 2a3 3 0 1 0 .002 6A3 3 0 0 0 12 9z"/></svg>
        </div>
        <div>
            <div class="text-xl font-medium text-black">¡Hola Mundo!</div>
            <p class="text-slate-500">Esto es Tailwind CSS v4 con CSS-First.</p>
        </div>
    </div>

    <div class="mt-8 text-center">
        <button class="bg-violet-600 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded-full">
            Haceme click
        </button>
    </div>

Fijate cómo las clases bg-violet-600 y hover:bg-violet-700 se corresponden con los colores que definimos en src/input.css bajo la directiva @theme. Esto demuestra que tu configuración CSS-First está funcionando a la perfección.

También podés ver cómo se usan clases responsivas, pseudoclases (como hover), y utilidades comunes de layout como flex, space-x-4 (para el espaciado entre ítems flex), mx-auto (para centrar un bloque), mt-10 (margen top), etc.

Un ejemplo más interactivo (no ejecutable directamente aquí, pero ilustrativo)

Imaginá que querés cambiar el fondo de la página o el tamaño de texto de un párrafo. Con el modo --watch activo, simplemente editás tu index.html:

<!-- ... -->
<body class="bg-zinc-100 font-sans">
    <div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4 mt-10">
        <!-- ... -->
        <div>
            <div class="text-2xl font-bold text-black">¡Hola Mundo!</div>
            <p class="text-slate-600 text-lg">Esto es Tailwind CSS v4 con CSS-First.</p>
        </div>
    </div>
    <!-- ... -->
</body>

Guardás index.html, y automáticamente Tailwind regenera output.css con las nuevas utilidades (bg-zinc-100, font-sans, text-2xl, font-bold, text-slate-600, text-lg). Refrescás el navegador y ¡listo! Los cambios están aplicados.

Buenas Prácticas y Errores Comunes con Tailwind CSS v4 CSS-First

Para que tu experiencia con Tailwind v4 sea lo más fluida posible, acá te dejo algunos tips y cosas a tener en cuenta:

1. Mantenete Actualizado (con precaución)

Recordá que tailwindcss@next es una versión en desarrollo. Esto significa que puede haber cambios de última hora, bugs o modificaciones en la API. Si estás usándolo en un proyecto personal o experimental, ¡dale con todo! Para proyectos en producción, quizás sea mejor esperar a la versión estable, o al menos estar al tanto de los changelogs.

2. @theme vs. tailwind.config.js

  • Usa @theme en src/input.css para la mayoría de tus tokens de diseño: Colores, fuentes, espaciados, breakpoints custom, etc. Es el lugar ideal para definir tu sistema de diseño de forma directa y legible.
  • Reservá tailwind.config.js para plugins, presets, o configuraciones muy complejas: Si necesitás integrar plugins de terceros, usar presets de Tailwind, o tenés una lógica de configuración que va más allá de simples tokens de diseño, ahí sí usá tailwind.config.js y apuntá a él con @config en tu input.css.

3. No olvides el --watch durante el desarrollo

Es fundamental para una experiencia de desarrollo ágil. Sin --watch, vas a tener que recompilar manualmente cada vez que cambies algo, y eso es un embole.

npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch

4. La Purga es Automática (¡Casi!)

Tailwind v4 sigue siendo "tree-shakable" por defecto, lo que significa que en el proceso de compilación final, solo se incluyen las clases que realmente usás en tus archivos. La configuración content en tu tailwind.config.js es crucial para que esto funcione correctamente. Asegurate de que cubra todos los archivos donde usás clases de Tailwind (HTML, JS, JSX, TSX, etc.).

// tailwind.config.js
module.exports = {
  content: [
    './index.html',
    './src/**/*.{js,ts,jsx,tsx,html}',
    // ¡Agregá todas las rutas donde tengas clases de Tailwind!
  ],
  theme: {},
  plugins: [],
}

5. @apply sigue existiendo, pero...

La directiva @apply para combinar clases de Tailwind en tu propio CSS sigue estando disponible. Sin embargo, la filosofía de Tailwind siempre fue priorizar la composición directa en el HTML. Con la v4 y el enfoque CSS-First, se refuerza aún más la idea de que tus tokens de diseño están en tu CSS, y tus componentes se construyen directamente con utilidades en el HTML. Usá @apply con moderación y solo cuando realmente simplifique algo complejo que no podés lograr fácilmente en HTML (por ejemplo, para estilos de base globales para elementos HTML planos o para componentes muy específicos que no se repiten mucho).

6. Integración con Frameworks de JS (Vite, Next.js, etc.)

Para este tutorial, usamos el CLI de Tailwind para simplificar. Pero en un proyecto real con frameworks como React, Vue o Svelte, vas a integrar Tailwind v4 a través de la configuración de tu bundler (Vite, Webpack, Parcel). Generalmente, esto implica configurar PostCSS en tu vite.config.js o next.config.js para que incluya Tailwind. La buena noticia es que el proceso sigue siendo similar al de versiones anteriores de Tailwind, ya que la integración suele ser a través de PostCSS.

Por ejemplo, con Vite, instalarías @vitejs/plugin-react (si usas React) y configurarías postcss.config.js y vite.config.js.

postcss.config.js (si lo necesitás):

// postcss.config.js
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

vite.config.js (ejemplo con React):

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  css: {
    postcss: './postcss.config.js', // Asegurate de que Vite use tu config de PostCSS
  },
})

Esto es solo para mostrarte que la integración sigue siendo posible y robusta, pero la configuración específica puede variar según tu stack.

7. Mantener la consistencia

Si empezás a definir colores en @theme en tu input.css, seguí esa convención para todos tus tokens. Evitá tener una parte de los colores en el tailwind.config.js y otra en el @theme, a menos que haya una razón muy específica y documentada para ello. La consistencia es clave para la mantenibilidad.

Conclusión: El Futuro de Tailwind CSS ya está Acá

¡Mirá vos! Acabás de ver cómo configurar y usar Tailwind CSS v4 con su innovador enfoque CSS-First. Este cambio no es menor; representa un paso adelante en la eficiencia, el rendimiento y la experiencia de desarrollo con Tailwind.

La posibilidad de definir tus tokens de diseño directamente en tu CSS, junto con un motor de compilación más liviano y performante, hace que Tailwind v4 sea una propuesta súper atractiva. Si bien todavía está en desarrollo, la dirección es clara: un Tailwind más rápido, más integrado con los estándares de CSS y con una curva de aprendizaje optimizada, especialmente para aquellos que se inician.

Resumen de lo aprendido:

  • Tailwind v4 introduce un enfoque CSS-First que simplifica la configuración.
  • Usás la directiva @theme en tu input.css para definir tus tokens de diseño (colores, fuentes, etc.).
  • @config te permite enlazar un tailwind.config.js si necesitás plugins o configuraciones avanzadas.
  • La instalación es con tailwindcss@next y postcss.
  • La compilación se hace con npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch.
  • El uso de clases en HTML permanece igual, lo que facilita la migración.

Próximos pasos:

Te animo a que experimentes con esta versión. Jugá con los colores, agregá más fuentes, definí tus propios breakpoints en @theme. La mejor forma de aprender es metiendo mano. A medida que la versión 4 se acerque a la estabilidad, seguramente vas a encontrar mucha más documentación y ejemplos en la comunidad. ¡Así que no te duermas y empezá a explorar el futuro de Tailwind CSS hoy mismo!

¡Hasta la próxima, desarrollador!

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario