Primeros pasos
Actualizando tus proyectos de Tailwind CSS de v3 a v4.
Tailwind CSS v4.0 es una nueva versión mayor del framework, así que aunque hemos trabajado muy duro para minimizar los cambios importantes (breaking changes), algunas actualizaciones son necesarias. Esta guía describe todos los pasos necesarios para actualizar tus proyectos de v3 a v4.
Tailwind CSS v4.0 está diseñado para Safari 16.4+, Chrome 111+ y Firefox 128+. Si necesitas dar soporte a navegadores más antiguos, quédate con v3.4 hasta que cambien tus requisitos de soporte de navegadores.
Si quieres actualizar un proyecto de v3 a v4, puedes usar nuestra herramienta de actualización para hacer la gran mayoría del trabajo pesado por ti:
$ npx @tailwindcss/upgrade
Para la mayoría de los proyectos, la herramienta de actualización automatizará todo el proceso de migración, incluyendo la actualización de tus dependencias, la migración de tu archivo de configuración a CSS y el manejo de cualquier cambio en tus archivos de plantilla.
La herramienta de actualización requiere Node.js 20 o superior, así que asegúrate de que tu entorno esté actualizado antes de ejecutarla.
Te recomendamos ejecutar la herramienta de actualización en una nueva rama, luego revisar cuidadosamente las diferencias (diff
) y probar tu proyecto en el navegador para asegurarte de que todos los cambios se vean correctos. Puede que necesites ajustar algunas cosas a mano en proyectos complejos, pero la herramienta te ahorrará mucho tiempo de cualquier manera.
También es una buena idea repasar todos los cambios importantes en v4 y entender bien qué ha cambiado, en caso de que haya otras cosas que necesites actualizar en tu proyecto que la herramienta de actualización no detecte.
En v3, el paquete tailwindcss
era un plugin de PostCSS, pero en v4 el plugin de PostCSS vive en un paquete dedicado @tailwindcss/postcss
.
Además, en v4 las importaciones y los prefijos de proveedor (vendor prefixing
) ahora se manejan automáticamente por ti, por lo que puedes eliminar postcss-import
y autoprefixer
si están en tu proyecto:
export default { plugins: { "postcss-import": {}, tailwindcss: {}, autoprefixer: {}, "@tailwindcss/postcss": {}, },};
Si estás usando Vite, te recomendamos migrar del plugin PostCSS a nuestro nuevo plugin dedicado de Vite para mejorar el rendimiento y obtener la mejor experiencia de desarrollo:
import { defineConfig } from "vite";import tailwindcss from "@tailwindcss/vite";export default defineConfig({ plugins: [ tailwindcss(), ],});
En v4, Tailwind CLI vive en un paquete dedicado @tailwindcss/cli
. Actualiza cualquiera de tus comandos de compilación para usar el nuevo paquete en su lugar:
npx tailwindcss -i input.css -o output.cssnpx @tailwindcss/cli -i input.css -o output.css
Aquí tienes una lista completa de todos los cambios importantes (breaking changes) en Tailwind CSS v4.0.
Nuestra herramienta de actualización se encargará de la mayoría de estos cambios automáticamente, así que te recomendamos encarecidamente usarla si puedes.
Tailwind CSS v4.0 está diseñado para navegadores modernos y apunta a Safari 16.4, Chrome 111 y Firefox 128. Dependemos de características modernas de CSS como @property
y color-mix()
para las características principales del framework, y Tailwind CSS v4.0 no funcionará en navegadores más antiguos.
Si necesitas dar soporte a navegadores más antiguos, te recomendamos quedarte con v3.4 por ahora. Estamos explorando activamente un modo de compatibilidad para ayudar a la gente a actualizar antes, sobre el que esperamos compartir más noticias en el futuro.
En v4 importas Tailwind usando una declaración @import
regular de CSS, no usando las directivas @tailwind
que usabas en v3:
@tailwind base;@tailwind components;@tailwind utilities;@import "tailwindcss";
Hemos eliminado cualquier utilidad que estuviera obsoleta en v3 y que no haya sido documentada durante varios años. Aquí tienes una lista de lo que se ha eliminado junto con la alternativa moderna:
Obsoleta | Reemplazo |
---|---|
bg-opacity-* | Usa modificadores de opacidad como bg-black/50 |
text-opacity-* | Usa modificadores de opacidad como text-black/50 |
border-opacity-* | Usa modificadores de opacidad como border-black/50 |
divide-opacity-* | Usa modificadores de opacidad como divide-black/50 |
ring-opacity-* | Usa modificadores de opacidad como ring-black/50 |
placeholder-opacity-* | Usa modificadores de opacidad como placeholder-black/50 |
flex-shrink-* | shrink-* |
flex-grow-* | grow-* |
overflow-ellipsis | text-ellipsis |
decoration-slice | box-decoration-slice |
decoration-clone | box-decoration-clone |
Hemos renombrado las siguientes utilidades en v4 para hacerlas más consistentes y predecibles:
v3 | v4 |
---|---|
shadow-sm | shadow-xs |
shadow | shadow-sm |
drop-shadow-sm | drop-shadow-xs |
drop-shadow | drop-shadow-sm |
blur-sm | blur-xs |
blur | blur-sm |
backdrop-blur-sm | backdrop-blur-xs |
backdrop-blur | backdrop-blur-sm |
rounded-sm | rounded-xs |
rounded | rounded-sm |
outline-none | outline-hidden |
ring | ring-3 |
Hemos renombrado las escalas predeterminadas de sombra, radio y desenfoque para asegurarnos de que cada utilidad tenga un valor nombrado. Las versiones "simples" (bare
) todavía funcionan por compatibilidad hacia atrás, pero las utilidades <utility>-sm
se verán diferentes a menos que se actualicen a sus respectivas versiones <utility>-xs
.
Para actualizar tu proyecto para estos cambios, reemplaza todas las utilidades de v3 con sus versiones de v4:
<input class="shadow-sm" /><input class="shadow-xs" /><input class="shadow" /><input class="shadow-sm" />
La utilidad outline
ahora establece outline-width: 1px
por defecto para ser más consistente con las utilidades de borde y anillo. Además, todas las utilidades outline-<number>
establecen por defecto outline-style
a solid
, omitiendo la necesidad de combinarlas con outline
:
<input class="outline outline-2" /><input class="outline-2" />
La utilidad outline-none
anteriormente no establecía realmente outline-style: none
, sino que establecía un contorno invisible que aún aparecería en el modo de colores forzados por razones de accesibilidad.
Para dejar esto más claro, hemos renombrado esta utilidad a outline-hidden
y hemos añadido una nueva utilidad outline-none
que realmente establece outline-style: none
.
Para actualizar tu proyecto para este cambio, reemplaza cualquier uso de outline-none
con outline-hidden
:
<input class="focus:outline-none" /><input class="focus:outline-hidden" />
En v3, la utilidad ring
añadía un anillo de 3px
. Hemos cambiado esto en v4 a 1px
para hacerlo consistente con los bordes y contornos.
Para actualizar tu proyecto para este cambio, reemplaza cualquier uso de ring
con ring-3
:
<input class="ring ring-blue-500" /><input class="ring-3 ring-blue-500" />
Hemos cambiado el selector utilizado por las utilidades space-x-*
y space-y-*
para abordar serios problemas de rendimiento en páginas grandes:
/* Antes */.space-y-4 > :not([hidden]) ~ :not([hidden]) { margin-top: 1rem;}/* Ahora */.space-y-4 > :not(:last-child) { margin-bottom: 1rem;}
Podrías ver cambios en tu proyecto si alguna vez estuviste usando estas utilidades con elementos inline, o si estabas añadiendo otros márgenes a los elementos hijos para ajustar su espaciado.
Si este cambio causa algún problema en tu proyecto, te recomendamos migrar a un layout flex o grid y usar gap
en su lugar:
<div class="space-y-4 p-4"> <!-- // Anterior --><div class="flex flex-col gap-4 p-4"> <!-- // Nuevo --> <label for="name">Nombre</label> <input type="text" name="name" /></div>
En v3, sobrescribir parte de un gradiente con una variante "reiniciaría" todo el gradiente, por lo que en este ejemplo el color to-*
sería transparente en modo oscuro en lugar de amarillo:
<div class="bg-gradient-to-r from-red-500 to-yellow-400 dark:from-blue-500"> <!-- ... --></div>
En v4, estos valores se preservan, lo cual es más consistente con cómo funcionan otras utilidades en Tailwind.
Esto significa que puede que necesites usar explícitamente via-none
si quieres "desactivar" un gradiente de tres paradas (three-stop
) de vuelta a un gradiente de dos paradas (two-stop
) en un estado específico:
<div class="bg-linear-to-r from-red-500 via-orange-400 to-yellow-400 dark:via-none dark:from-blue-500 dark:to-teal-400"> <!-- ... --></div>
En v3, la utilidad container
tenía varias opciones de configuración como center
y padding
que ya no existen en v4.
Para personalizar la utilidad container
en v4, extiéndela usando la directiva @utility
:
@utility container { margin-inline: auto; padding-inline: 2rem;}
En v3, las utilidades border-*
y divide-*
usaban tu color configurado gray-200
por defecto. Hemos cambiado esto a currentColor
en v4 para hacer Tailwind menos dogmático y coincidir con los valores predeterminados del navegador.
Para actualizar tu proyecto para este cambio, asegúrate de especificar un color en cualquier lugar donde estés usando una utilidad border-*
o divide-*
:
<div class="border border-gray-200 px-2 py-3 ..."> <!-- ... --></div>
Alternativamente, añade estos estilos base a tu proyecto para preservar el comportamiento de v3:
@layer base { *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--color-gray-200, currentColor); }}
Hemos cambiado el ancho de la utilidad ring
de 3px a 1px y hemos cambiado el color predeterminado de blue-500
a currentColor
para hacer las cosas más consistentes con las utilidades border-*
, divide-*
y outline-*
.
Para actualizar tu proyecto para estos cambios, reemplaza cualquier uso de ring
con ring-3
:
<button class="focus:ring ..."><button class="focus:ring-3 ..."> <!-- ... --></button>
Luego asegúrate de añadir ring-blue-500
en cualquier lugar donde dependieras del color de anillo predeterminado:
<button class="focus:ring-3 focus:ring-blue-500 ..."> <!-- ... --></button>
Alternativamente, añade estas variables de tema a tu CSS para preservar el comportamiento de v3:
@theme { --default-ring-width: 3px; --default-ring-color: var(--color-blue-500);}
Ten en cuenta, sin embargo, que estas variables solo son compatibles por razones de compatibilidad, y no se consideran un uso idiomático de Tailwind CSS v4.0.
Hemos hecho un par de pequeños cambios en los estilos base en Preflight en v4:
En v3, el texto del placeholder usaba tu color configurado gray-400
por defecto. Hemos simplificado esto en v4 para simplemente usar el color de texto actual con una opacidad del 50%.
Probablemente ni siquiera notarás este cambio (incluso podría hacer que tu proyecto se vea mejor), pero si quieres preservar el comportamiento de v3, añade este CSS a tu proyecto:
@layer base { input::placeholder, textarea::placeholder { color: var(--color-gray-400); }}
Los botones ahora usan cursor: default
en lugar de cursor: pointer
para coincidir con el comportamiento predeterminado del navegador.
Si quieres continuar usando cursor: pointer
por defecto, añade estos estilos base a tu CSS:
@layer base { button:not(:disabled), [role="button"]:not(:disabled) { cursor: pointer; }}
Preflight ahora restablece los márgenes en los elementos <dialog>
para ser consistente con cómo se restablecen otros elementos.
Si todavía quieres que los diálogos estén centrados por defecto, añade este CSS a tu proyecto:
@layer base { dialog { margin: auto; }}
Los prefijos ahora se ven como variantes y siempre están al principio del nombre de la clase:
<div class="tw:flex tw:bg-red-500 tw:hover:bg-red-600"> <!-- ... --></div>
Cuando uses un prefijo, aún debes configurar tus variables de tema como si no estuvieras usando un prefijo:
@import "tailwindcss" prefix(tw);@theme { --font-display: "Satoshi", "sans-serif"; --breakpoint-3xl: 120rem; --color-avocado-100: oklch(0.99 0 0); --color-avocado-200: oklch(0.98 0.04 113.22); --color-avocado-300: oklch(0.94 0.11 115.03); /* ... */}
Las variables CSS generadas sí incluirán un prefijo para evitar conflictos con cualquier variable existente en tu proyecto:
:root { --tw-font-display: "Satoshi", "sans-serif"; --tw-breakpoint-3xl: 120rem; --tw-color-avocado-100: oklch(0.99 0 0); --tw-color-avocado-200: oklch(0.98 0.04 113.22); --tw-color-avocado-300: oklch(0.94 0.11 115.03); /* ... */}
En v3, cualquier clase personalizada que definieras dentro de @layer utilities
o @layer components
sería reconocida por Tailwind como una verdadera clase de utilidad y funcionaría automáticamente con variantes como hover
, focus
o lg
, con la diferencia de que @layer components
siempre vendría primero en la hoja de estilos generada.
En v4 estamos usando capas de cascada nativas y ya no secuestramos la regla @layer
, por lo que hemos introducido la API @utility
como reemplazo:
@layer utilities { .tab-4 { tab-size: 4; }}@utility tab-4 { tab-size: 4;}
Las utilidades personalizadas ahora también se ordenan según la cantidad de propiedades que definen. Esto significa que utilidades de componentes como este .btn
pueden ser sobrescritas por otras utilidades de Tailwind sin configuración adicional:
@layer components { .btn { border-radius: 0.5rem; padding: 0.5rem 1rem; background-color: ButtonFace; }}@utility btn { border-radius: 0.5rem; padding: 0.5rem 1rem; background-color: ButtonFace;}
Aprende más sobre cómo registrar utilidades personalizadas en la documentación de adición de utilidades personalizadas.
En v3, las variantes apiladas se aplicaban de derecha a izquierda, pero en v4 las hemos actualizado para que se apliquen de izquierda a derecha para parecerse más a la sintaxis de CSS.
Para actualizar tu proyecto para este cambio, invierte el orden de cualquier variante apilada sensible al orden en tu proyecto:
<ul class="py-4 first:*:pt-0 last:*:pb-0"><ul class="py-4 *:first:pt-0 *:last:pb-0"> <li>Uno</li> <li>Dos</li> <li>Tres</li></ul>
Probablemente tengas muy pocas de estas, si es que tienes alguna: la variante de hijo directo (*
) y cualquier variante del plugin de tipografía (prose-headings
) son las más probables que podrías estar usando, e incluso entonces solo si las has apilado con otras variantes.
En v3 podías usar variables CSS como valores arbitrarios sin var()
, pero las actualizaciones recientes de CSS significan que esto a menudo puede ser ambiguo, por lo que hemos cambiado la sintaxis para esto en v4 para usar paréntesis en lugar de corchetes.
Para actualizar tu proyecto para este cambio, reemplaza el uso de la sintaxis abreviada de variable antigua con la nueva sintaxis abreviada de variable:
<div class="bg-[--brand-color]"></div><div class="bg-(--brand-color)"></div>
En v4 hemos actualizado la variante hover
para que solo se aplique cuando el dispositivo de entrada principal admita hover:
@media (hover: hover) { .hover\:underline:hover { text-decoration: underline; }}
Esto puede crear problemas si has construido tu sitio de manera que dependa de que los dispositivos táctiles activen el hover al tocar. Si esto es un problema para ti, puedes sobrescribir la variante hover
con tu propia variante que use la implementación antigua:
@custom-variant hover (&:hover);
Sin embargo, generalmente recomendamos tratar la funcionalidad hover como una mejora, y no depender de ella para que tu sitio funcione, ya que los dispositivos táctiles realmente no tienen la capacidad de hacer hover.
Las utilidades transition
y transition-color
ahora incluyen la propiedad outline-color
.
Esto significa que si estabas añadiendo un contorno con un color personalizado en focus, verás la transición de color desde el color predeterminado. Para evitar esto, asegúrate de establecer el color del contorno incondicionalmente, o establécelo explícitamente para ambos estados:
<button class="transition hover:outline-2 hover:outline-cyan-500"></button><button class="outline-cyan-500 transition hover:outline-2"></button>
En v3 había una opción corePlugins
que podías usar para deshabilitar completamente ciertas utilidades en el framework. Esto ya no es compatible en v4.
Dado que v4 incluye variables CSS para todos tus valores de tema, recomendamos usar esas variables en lugar de la función theme()
siempre que sea posible:
.my-class { background-color: theme(colors.red.500); background-color: var(--color-red-500);}
Para los casos en los que todavía necesites usar la función theme()
(como en media queries donde las variables CSS no son compatibles), debes usar el nombre de la variable CSS en lugar de la antigua notación de puntos:
@media (width >= theme(screens.xl)) { // Anterior@media (width >= theme(--breakpoint-xl)) { // Nuevo /* ... */}
Los archivos de configuración JavaScript todavía son compatibles por compatibilidad hacia atrás, pero ya no se detectan automáticamente en v4.
Si todavía necesitas usar un archivo de configuración JavaScript, puedes cargarlo explícitamente usando la directiva @config
:
@config "../../tailwind.config.js";
Las opciones corePlugins
, safelist
y separator
de la configuración basada en JavaScript no son compatibles en v4.0.
En v3 exportamos una función resolveConfig
que podías usar para convertir tu configuración basada en JavaScript en un objeto plano que podías usar en tu otro JavaScript.
Hemos eliminado esto en v4 con la esperanza de que la gente pueda usar las variables CSS que generamos directamente en su lugar, lo cual es mucho más simple y reducirá significativamente el tamaño de tu paquete (bundle size
).
Por ejemplo, la popular biblioteca Motion para React te permite animar hacia y desde valores de variables CSS:
<motion.div animate={{ backgroundColor: "var(--color-blue-500)" }} />
Si necesitas acceder a un valor resuelto de variable CSS en JS, puedes usar getComputedStyle
para obtener el valor de una variable de tema en el document root
:
let styles = getComputedStyle(document.documentElement);let shadow = styles.getPropertyValue("--shadow-xl");
En v4, las hojas de estilo que se empaquetan (bundled
) por separado de tu archivo CSS principal (por ejemplo, archivos CSS modules, bloques <style>
en Vue, Svelte o Astro, etc.) no tienen acceso a las variables de tema, utilidades personalizadas y variantes personalizadas definidas en otros archivos.
Para hacer que estas definiciones estén disponibles en estos contextos, usa @reference
para importarlas sin duplicar ningún CSS en tu paquete:
<template> <h1>¡Hola mundo!</h1></template><style> @reference "../../app.css"; // Referencia al archivo CSS principal h1 { @apply text-2xl font-bold text-red-500; }</style>
Alternativamente, puedes usar tus variables de tema CSS directamente en lugar de usar @apply
, lo que también mejorará el rendimiento ya que Tailwind no necesitará procesar estos estilos:
<template> <h1>¡Hola mundo!</h1></template><style> h1 { color: var(--text-red-500); // Usa la variable CSS directamente }</style>
Puedes encontrar más documentación sobre cómo usar Tailwind con CSS modules.