1. Primeros pasos
  2. Guía de actualización

Primeros pasos

Guía de actualización

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.

Usando la herramienta de actualización

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:

Terminal
$ 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.

Actualizando manualmente

Usando PostCSS

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:

postcss.config.mjs
export default {
plugins: {
"postcss-import": {},
tailwindcss: {},
autoprefixer: {},
"@tailwindcss/postcss": {},
},
};

Usando Vite

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:

vite.config.ts
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [
tailwindcss(),
],
});

Usando Tailwind CLI

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:

Terminal
npx tailwindcss -i input.css -o output.css
npx @tailwindcss/cli -i input.css -o output.css

Cambios desde v3

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.

Requisitos del navegador

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.

Eliminadas las directivas @tailwind

En v4 importas Tailwind usando una declaración @import regular de CSS, no usando las directivas @tailwind que usabas en v3:

CSS
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";

Eliminadas utilidades obsoletas

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:

ObsoletaReemplazo
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-ellipsistext-ellipsis
decoration-slicebox-decoration-slice
decoration-clonebox-decoration-clone

Utilidades renombradas

Hemos renombrado las siguientes utilidades en v4 para hacerlas más consistentes y predecibles:

v3v4
shadow-smshadow-xs
shadowshadow-sm
drop-shadow-smdrop-shadow-xs
drop-shadowdrop-shadow-sm
blur-smblur-xs
blurblur-sm
backdrop-blur-smbackdrop-blur-xs
backdrop-blurbackdrop-blur-sm
rounded-smrounded-xs
roundedrounded-sm
outline-noneoutline-hidden
ringring-3

Actualizadas las escalas de sombra, radio y desenfoque

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:

HTML
<input class="shadow-sm" />
<input class="shadow-xs" />
<input class="shadow" />
<input class="shadow-sm" />

Utilidad de contorno renombrada

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:

HTML
<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:

HTML
<input class="focus:outline-none" />
<input class="focus:outline-hidden" />

Cambio en el ancho predeterminado del anillo

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:

HTML
<input class="ring ring-blue-500" />
<input class="ring-3 ring-blue-500" />

Selector de espacio entre elementos

Hemos cambiado el selector utilizado por las utilidades space-x-* y space-y-* para abordar serios problemas de rendimiento en páginas grandes:

CSS
/* 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:

HTML
<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>

Usando variantes con gradientes

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:

HTML
<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:

HTML
<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>

Configuración del contenedor

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:

CSS
@utility container {
margin-inline: auto;
padding-inline: 2rem;
}

Color de borde predeterminado

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:

CSS
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}

Ancho y color de anillo predeterminados

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:

CSS
@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.

Cambios en Preflight

Hemos hecho un par de pequeños cambios en los estilos base en Preflight en v4:

Nuevo color de placeholder predeterminado

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:

CSS
@layer base {
input::placeholder,
textarea::placeholder {
color: var(--color-gray-400);
}
}

Los botones usan el cursor predeterminado

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:

CSS
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}

Márgenes de diálogo eliminados

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:

CSS
@layer base {
dialog {
margin: auto;
}
}

Usando un prefijo

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 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);
/* ... */
}

Añadiendo utilidades personalizadas

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:

CSS
@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:

CSS
@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.

Orden de apilamiento de variantes

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:

HTML
<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.

Variables en valores arbitrarios

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:

HTML
<div class="bg-[--brand-color]"></div>
<div class="bg-(--brand-color)"></div>

Estilos hover en móviles

En v4 hemos actualizado la variante hover para que solo se aplique cuando el dispositivo de entrada principal admita hover:

CSS
@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:

CSS
@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.

Transición de outline-color

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:

HTML
<button class="transition hover:outline-2 hover:outline-cyan-500"></button>
<button class="outline-cyan-500 transition hover:outline-2"></button>

Deshabilitando plugins principales

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.

Usando la función theme()

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:

CSS
.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:

CSS
@media (width >= theme(screens.xl)) { // Anterior
@media (width >= theme(--breakpoint-xl)) { // Nuevo
/* ... */
}

Usando un archivo de configuración JavaScript

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:

CSS
@config "../../tailwind.config.js";

Las opciones corePlugins, safelist y separator de la configuración basada en JavaScript no son compatibles en v4.0.

Valores del tema en JavaScript

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:

JSX
<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:

spaghetti.js
let styles = getComputedStyle(document.documentElement);
let shadow = styles.getPropertyValue("--shadow-xl");

Usando @apply con Vue, Svelte o CSS modules

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:

Vue
<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:

Vue
<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.

Copyright © 2025 Tailwind Labs Inc.·Política de Marca Registrada