Cambiar tema

Tailwind CSS v4: novedades, rendimiento y guía de migración

Easton editorial illustration: responsive layout folding board

35 milisegundos: tiempo de build incremental en Tailwind v3. En v4, la misma operación tarda unos 192 microsegundos.

Al principio no me lo creí — suena a copy de marketing. Pero tras migrar y ver el HMR pasar de 340 ms a 12 ms, quedó claro: Tailwind iba en serio.

Eso es el motor Oxide reescrito en Rust. No es placebo: cambias un padding y la página se actualiza antes de que parpadees. v4 también mueve la config a CSS, simplifica la instalación y actualiza utilidades (modificadores de opacidad, container queries, transforms 3D…).

Este artículo desglosa esos cambios y te deja una checklist de migración que puedes seguir paso a paso.

Motor Oxide: ¿por qué v4 es tan rápido?

¿Te ha pasado? Cambias un color, guardas y miras el navegador dos o tres segundos hasta ver el cambio. En proyectos grandes, los builds incrementales de Tailwind v3 pueden generar ansiedad — sobre todo con deadline encima.

El motor Oxide de v4 va directo a ese dolor. El equipo no parcheó el motor JS: reescribió el compilador en Rust desde cero. Decisión arriesgada, con beneficios reales.

¿Cuánto mejora el rendimiento?

Los benchmarks oficiales con el proyecto Catalyst son claros:

Escenariov3.4v4.0Mejora
Build completo378 ms100 ms3,78×
Incremental (CSS cambió)44 ms5 ms8,8×
Incremental (sin cambio CSS)35 ms192 µs182×

El último dato impresiona: si solo cambias HTML sin clases nuevas, v4 entra en microsegundos — imperceptible.

Datos de un proyecto en producción (500+ componentes):

Métricav3.4v4.0Cambio
Build en frío12,3 s1,8 s85 % más rápido
Arranque dev server4,2 s0,8 s81 % más rápido
Actualización HMR340 ms12 ms96 % más rápido
CSS producción48 KB31 KB35 % menos
Memoria180 MB45 MB75 % menos
96 %
Mejora de velocidad HMR

Bajar el HMR de 340 ms a 12 ms cambia la experiencia de desarrollo. Antes había una pausa visible; ahora es casi instantáneo.

¿Qué hizo bien Oxide?

El núcleo es Rust + Lightning CSS. Rust aporta rendimiento, pero el cambio de arquitectura importa más:

Toolchain unificado. En v3, Tailwind dependía del ecosistema PostCSS: autoprefixer, cssnano, etc. v4 lo integra y solo usa Lightning CSS. Menos capas, más velocidad.

Detección inteligente de contenido. Antes configurabas content en tailwind.config.js. v4 lee .gitignore y el grafo de módulos y descubre archivos solo. Menos config, más rapidez.

CSS nativo. v4 usa @layer, @property, color-mix() y otras APIs modernas soportadas por el navegador, sin transformaciones extra en compile time.

No hace falta dominar cada detalle técnico. Lo que cuenta: builds más rápidos, menos configuración, mejor DX.

Configuración CSS-first: adiós tailwind.config.js

Es el cambio más grande de v4 y también el de mayor coste de migración.

Antes escribíamos en tailwind.config.js; ahora va al CSS con @theme. Al principio costó — años de config JS y de repente variables CSS. Tras usarlo un tiempo, encaja mejor con el modo de pensar CSS.

Migración de config: antes y después

Ejemplo mínimo — color primario:

// v3: tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: '#3b82f6',
      },
    },
  },
}

En v4, todo en CSS:

/* v4: app.css */
@import "tailwindcss";

@theme {
  --color-primary: #3b82f6;
}

Nota: primary pasa a --color-primary por reglas estrictas de prefijos.

Tabla de prefijos de variables

Config v3Prefijo v4Ejemplo
colors—color-*—color-primary: #3b82f6
spacing—spacing-*—spacing-128: 32rem
fontSize—text-*—text-xs: 0.75rem
fontFamily—font-*—font-sans: “Inter”
borderRadius—radius-*—radius-lg: 0.5rem
screens—breakpoint-*—breakpoint-md: 768px
boxShadow—shadow-*—shadow-card: 0 4px 12px rgba(0,0,0,0.1)
animation—animate-*—animate-spin: spin 1s linear infinite

Al inicio parece verboso, pero no adivinas nombres: tamaños de fuente → --text-*.

Ejemplo de config más compleja

Config v3:

// v3: tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          light: '#f0f9ff',
          DEFAULT: '#0ea5e9',
          dark: '#0369a1',
        },
      },
      fontFamily: {
        display: ['Cal Sans', 'sans-serif'],
      },
      animation: {
        'fade-in': 'fadeIn 0.5s ease-out',
      },
    },
  },
  plugins: [
    require('@tailwindcss/typography'),
  ],
}

Migrado a v4:

/* v4: app.css */
@import "tailwindcss";

@theme {
  /* Colores */
  --color-brand-light: #f0f9ff;
  --color-brand: #0ea5e9;
  --color-brand-dark: #0369a1;

  /* Fuentes */
  --font-display: "Cal Sans", sans-serif;

  /* Animaciones */
  --animate-fade-in: fadeIn 0.5s ease-out;
}

/* Plugins */
@plugin "@tailwindcss/typography";

Cambios clave:

  1. Colores aplanados: brand.light--color-brand-light
  2. Plugins con @plugin: sin require en JS
  3. Sin sufijo DEFAULT: --color-brand es el default de brand

Modo oscuro

v3:

// v3
module.exports = {
  darkMode: 'class', // o 'media'
}

v4 usa media por defecto. Para class:

/* v4 */
@import "tailwindcss";
@variant dark (&:where(.dark, .dark *));

Aplica estilos dark cuando el elemento o un padre tiene .dark.

Detección de contenido

Antes especificabas archivos:

// v3
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './public/index.html',
  ],
}

v4 lee .gitignore, ignora exclusiones y escanea el proyecto. Estructuras raras: @source:

/* v4 */
@import "tailwindcss";
@source "../node_modules/my-ui-lib";

Ventaja: toda la config de estilos en un CSS, sin saltar entre JS y CSS. Inconveniente: curva de aprendizaje si venías de JS.

Instalación e integración: experiencia casi sin config

Instalar v3: tres paquetes, config, PostCSS, array content… No es terrible, pero en cada proyecto nuevo se repite.

v4 lo reduce al mínimo.

Instalación mínima

Con Vite, dos pasos:

# 1. Instalar
npm install tailwindcss @tailwindcss/vite

# 2. Una línea en vite.config.js
import tailwindcss from '@tailwindcss/vite'

export default {
  plugins: [tailwindcss()],
}

Y en el CSS:

/* app.css o index.css */
@import "tailwindcss";

Listo: sin tailwind.config.js, sin postcss.config.js, sin content.

Tres formas de integración

Vite (recomendado):

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'

export default {
  plugins: [tailwindcss()],
}

PostCSS:

npm install tailwindcss @tailwindcss/postcss
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

CLI:

npx tailwindcss -i input.css -o output.css --watch

La mayoría de proyectos modernos: Vite. PostCSS para migraciones legacy; CLI sin pipeline de build.

Cómo funciona la detección automática

v4 no pide content. Lee .gitignore, excluye node_modules, dist, etc., y busca clases Tailwind en el resto.

Requisito: estructura Node.js estándar. Plantillas fuera del árbol normal:

@import "tailwindcss";
@source "../templates";  /* Ruta manual */

Bonus: archivos nuevos sin tocar config. Antes actualizabas content por cada componente; ahora creas el archivo y funciona.

Cambios breaking y checklist de migración

Núcleo de la migración. La mayoría sigue patrones; hay herramienta oficial.

Modificadores de opacidad

El cambio con más impacto. v3:

<!-- v3 -->
<div class="bg-blue-500 bg-opacity-50">...</div>

v4 integra opacidad en el color:

<!-- v4 -->
<div class="bg-blue-500/50">...</div>

También texto y bordes:

<!-- Opacidad en texto -->
<p class="text-gray-900/75">...</p>

<!-- Opacidad en borde -->
<div class="border-red-500/30">...</div>

bg-opacity-* y similares: elimínalos; v4 no los soporta.

Utilidades renombradas

Clase v3Clase v4Notas
flex-growgrowNombre corto
flex-grow-*grow-*Nombre corto
flex-shrinkshrinkNombre corto
flex-shrink-*shrink-*Nombre corto
overflow-ellipsistext-ellipsisReagrupación
decoration-slicebox-decoration-sliceReagrupación
shadow-smshadow-xsTamaños
shadowshadow-smTamaños
rounded-smrounded-xsTamaños
roundedrounded-smTamaños
outline-noneoutline-hiddenSemántica

shadowshadow-sm; shadow-smshadow-xs: nombres de tamaño más coherentes.

Valores por defecto

Pueden romper estilos visuales:

Color de border: v3 gray-200, v4 currentColor (sigue el color del texto).

<!-- v3: borde gris -->
<div class="border text-blue-500">Borde gray-200</div>

<!-- v4: borde sigue al texto -->
<div class="border text-blue-500">Borde blue-500</div>

Ring: v3 3 px blue-500; v4 1 px currentColor.

<!-- v3: ring azul 3 px -->
<button class="ring">...</button>

<!-- v4: ring currentColor 1 px -->
<button class="ring">...</button>

<!-- Efecto v3 -->
<button class="ring-3 ring-blue-500">...</button>

Checklist completa

En orden:

  1. Actualizar dependencias
   npm install tailwindcss@latest @tailwindcss/vite@latest
   
  1. Herramienta automática
   npx @tailwindcss/upgrade
   

Convierte @tailwind, opacidad, renombrados, etc.

  1. CSS de entrada
   /* v3 */
   @tailwind base;
   @tailwind components;
   @tailwind utilities;

   /* v4 */
   @import "tailwindcss";
   
  1. Migrar config a bloque @theme en CSS.

  2. Plugins con @plugin:

   @plugin "@tailwindcss/typography";
   
  1. Opacidad: busca bg-opacity, text-opacity, border-opacity.

  2. Renombrados: shadow-*, rounded-*, flex-grow-*, flex-shrink-*.

  3. Defaults: border y ring.

  4. Regresión visual: tests visuales si los tienes.

La herramienta cubre ~80 %; el 20 % restante son defaults que solo tú puedes validar.

Novedades: Container Queries, transforms 3D y más

Además de rendimiento y config, v4 trae utilidades prácticas.

Container Queries nativas

Antes hacía falta plugin; ahora viene integrado:

<!-- Contenedor -->
<div class="@container">
  <!-- Responsive al ancho del contenedor -->
  <div class="@md:grid-cols-2 @lg:grid-cols-3">
    ...
  </div>
</div>

@containercontainer-type: inline-size; @md: es breakpoint de container query. Similar a md:, con @ delante.

Ideal en librerías de componentes: el estilo responde al padre, no solo al viewport.

Utilidades 3D Transform

<!-- Perspectiva 3D -->
<div class="perspective-distant">
  <!-- Rotación eje X -->
  <div class="rotate-x-45">...</div>
</div>

<!-- Rotación eje Y -->
<div class="rotate-y-12">...</div>

<!-- Escala eje Z -->
<div class="scale-z-150">...</div>

Clases: rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, perspective-*, translate-z-*… Flips de tarjeta y menús 3D más sencillos.

Variante @starting-style

Con la regla CSS @starting-style, para el primer render:

<!-- De transparente a opaco al aparecer -->
<div class="starting:opacity-0 opacity-100 transition-opacity">
  ...
</div>

Animación de entrada sin JavaScript. Antes animate-fade-in custom; ahora una clase.

Variante not-*

Pseudo-clase :not():

<!-- Todos menos el último -->
<li class="not-last:mb-4">...</li>

<!-- Botones no disabled -->
<button class="not-disabled:opacity-100">...</button>

Más claro que trucos inversos tipo last:mb-0.

Gradient API ampliada

<!-- Gradiente cónico -->
<div class="bg-conic/from-red-500 via-yellow-500 to-blue-500">...</div>

<!-- Gradiente radial -->
<div class="bg-radial from-white to-transparent">...</div>

<!-- Modo de interpolación -->
<div class="bg-linear-to-r from-blue-500 to-purple-500 via-oklch">...</div>

via-oklch suaviza transiciones, sobre todo al cambiar espacio de color.

Conclusión

¿Merece la pena actualizar?

Si el proyecto sigue activo, sí. HMR de cientos de ms a ~12 ms ahorra tiempo cada día. CSS más pequeño y menos memoria — sobre todo en monorepos grandes.

El coste está en config y renombrados. npx @tailwindcss/upgrade automatiza lo repetitivo. En mi prueba, un proyecto mediano (200+ componentes) migró en medio día con pruebas.

Proyectos nuevos: v4 directo. Instalación mínima, detección automática, CSS-first — no hay motivo para quedarse en v3.

Compatibilidad: Safari 16.4+, Chrome 111+, Firefox 128+. Navegadores viejos: espera.

Acciones:

Guía de migración a Tailwind CSS v4

Pasos completos para actualizar de Tailwind v3 a v4

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Actualizar dependencias

    Ejecuta npm para instalar la última versión:

    ```bash
    npm install tailwindcss@latest @tailwindcss/vite@latest
    ```

    Si usas integración PostCSS:
    ```bash
    npm install tailwindcss@latest @tailwindcss/postcss@latest
    ```
  2. 2

    Step 2: Ejecutar herramienta de migración automática

    Tailwind ofrece una herramienta de migración en un comando:

    ```bash
    npx @tailwindcss/upgrade
    ```

    Esta herramienta convierte automáticamente:
    • Directivas @tailwind a @import "tailwindcss"
    • Clases de opacidad de bg-opacity-* a sintaxis /50
    • Utilidades renombradas (shadow-sm → shadow-xs, etc.)
    • Archivo de config al formato CSS @theme
  3. 3

    Step 3: Convertir el CSS de entrada

    Sustituye las tres directivas @tailwind por una sola @import:

    ```css
    /* Elimina esto */
    @tailwind base;
    @tailwind components;
    @tailwind utilities;

    /* Sustituye por */
    @import "tailwindcss";
    ```
  4. 4

    Step 4: Migrar config personalizada a CSS

    Mueve la configuración del theme de tailwind.config.js al CSS:

    ```css
    @import "tailwindcss";

    @theme {
    /* Colores */
    --color-brand: #0ea5e9;

    /* Fuentes */
    --font-display: "Cal Sans", sans-serif;

    /* Animaciones */
    --animate-fade-in: fadeIn 0.5s ease-out;
    }
    ```

    Reglas de nombres: colors → --color-*, fontSize → --text-*
  5. 5

    Step 5: Actualizar importación de plugins

    Los plugins JS usan la directiva @plugin:

    ```css
    /* Antes: en tailwind.config.js */
    // plugins: [require('@tailwindcss/typography')]

    /* Ahora: en el CSS */
    @plugin "@tailwindcss/typography";
    ```
  6. 6

    Step 6: Revisar cambios de valores por defecto

    Presta atención a dos cambios:

    • **Color de border**: de gray-200 a currentColor
    - Si necesitas el borde gris original, añade border-gray-200 explícitamente

    • **Ring por defecto**: de 3 px blue-500 a 1 px currentColor
    - Para el efecto v3, usa ring-3 ring-blue-500
  7. 7

    Step 7: Probar y corregir estilos

    Arranca el servidor de desarrollo y revisa cambios visuales:

    ```bash
    npm run dev
    ```

    Comprueba:
    • Estilos de opacidad
    • Tamaños de shadow y rounded
    • Colores de borde vs diseño
    • Tests de regresión visual (si los tienes)

FAQ

¿Cuál es la mayor diferencia entre Tailwind CSS v4 y v3?
Tres cambios clave: el motor Oxide reescrito en Rust mejora el HMR ~96%; la configuración pasa de JS a CSS con @theme; e instalación simplificada — proyectos Vite en 2 pasos.
¿Cuánto tarda migrar a Tailwind v4?
Un proyecto mediano (200+ componentes) suele llevar medio día. La herramienta automática cubre ~80%; el 20% restante son revisiones de defaults y configs especiales.
¿Qué compatibilidad de navegadores exige v4?
Safari 16.4+, Chrome 111+, Firefox 128+, por @layer, @property, color-mix(), etc. Si necesitas navegadores antiguos, conviene esperar.
¿Qué cubre la herramienta de migración automática?
Conversión de @tailwind, sintaxis de opacidad (bg-opacity-50 → /50), utilidades renombradas (shadow-sm → shadow-xs) y config JS a CSS @theme. No corrige diferencias por cambios de valores por defecto.
¿v4 sigue necesitando configurar el array content?
No. v4 lee .gitignore, excluye directorios irrelevantes y escanea clases Tailwind. Casos especiales: directiva @source.
¿Qué hacer si los estilos no coinciden tras actualizar desde v3?
Revisa tres defaults: border de gray-200 a currentColor, ring de 3 px blue-500 a 1 px currentColor, y renombrado de shadow/rounded. Añade clases explícitas donde haga falta.
¿Qué novedades de v4 merecen atención?
Container Queries nativas (@container), utilidades 3D (rotate-x/y/z, perspective-*), variante @starting-style, variante not-* y Gradient API ampliada (cónico, radial, interpolación oklch).

8 min de lectura · Publicado el: 25 mar 2026 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog