Tailwind CSS v4.1: Sombras de texto, máscaras y muchísimo más

Adam Wathan
Dan Hollick

No estaba seguro de que alguna vez sucedería, pero lo hicimos: lanzamos una versión de Tailwind CSS que incluye utilitarios de text-shadow.

Tailwind CSS v4.1 está aquí y está repleto de nuevos utilitarios, variantes y mejoras en la experiencia del desarrollador que te ayudarán (o a tu LLM, cobarde) a construir experiencias interactivas aún mejores.

Aquí tienes todo lo mejor que incluimos en esta versión:

Eso es todo lo bueno, pero hay algunas otras pequeñas cosas escondidas en las notas de la versión que quizás quieras revisar también.

Actualiza tus proyectos instalando la última versión de tailwindcss desde npm:

Usando la CLI de Tailwind
npm install tailwindcss@latest @tailwindcss/cli@latest
Usando Vite
npm install tailwindcss@latest @tailwindcss/vite@latest
Usando PostCSS
npm install tailwindcss@latest @tailwindcss/postcss@latest

Nuevos utilitarios text-shadow-*

Llevamos amenazando con añadir sombras de texto durante al menos los últimos seis años y hoy finalmente están aquí.

Hemos añadido cinco sombras de texto al tema por defecto, desde text-shadow-2xs hasta text-shadow-lg. Son particularmente útiles para hacer que los encabezados destaquen sobre un fondo recargado:

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

<p class="text-shadow-2xs ...">El rápido zorro marrón...</p>
<p class="text-shadow-xs ...">El rápido zorro marrón...</p>
<p class="text-shadow-sm ...">El rápido zorro marrón...</p>
<p class="text-shadow-md ...">El rápido zorro marrón...</p>
<p class="text-shadow-lg ...">El rápido zorro marrón...</p>

Puedes cambiar el color de la sombra usando los utilitarios text-shadow-<color>. Por ejemplo, puedes crear una especie de efecto de relieve usando una pequeña sombra blanca sobre texto oscuro:

<button class="text-sky-950 text-shadow-2xs text-shadow-sky-300 ...">Reserva una demo</button>
<button class="text-gray-950 dark:text-white dark:text-shadow-2xs ...">Ver precios</button>

Si solo quieres ajustar la opacidad de una sombra de texto sin cambiar el color, puedes añadir un modificador de opacidad directamente en los utilitarios de tamaño de sombra de texto como text-shadow-lg.

Por ejemplo, text-shadow-lg/50 es lo mismo que establecer text-shadow-lg y text-shadow-black/50 al mismo tiempo:

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

El rápido zorro marrón salta sobre el perro perezoso.

<p class="text-shadow-lg ...">El rápido zorro marrón...</p>
<p class="text-shadow-lg/20 ...">El rápido zorro marrón...</p>
<p class="text-shadow-lg/30 ...">El rápido zorro marrón...</p>

Consulta la documentación de text-shadow para más detalles.


Enmascara elementos con los utilitarios mask-*

Una de las características más geniales del CSS moderno es la capacidad de usar imágenes y gradientes como máscaras, básicamente usando la opacidad de una imagen para ocultar ciertas partes de un elemento:

Velocidad

Hecho para usuarios avanzados

Trabaja más rápido que nunca con nuestros atajos de teclado

<div class="mx-auto flex items-center p-16 max-sm:p-8">
<img
src="/img/keyboard.png"
class="mask-radial-from-transparent mask-radial-from-15% mask-radial-to-black mask-radial-to-55% mask-radial-at-right ..."
/>
<div class="font-medium">
<p class="font-mono text-xs text-blue-500 uppercase dark:text-blue-400">Velocidad</p>
<p class="mt-2 text-base text-gray-700 dark:text-gray-300">Hecho para usuarios avanzados</p>
<p class="mt-1 text-sm leading-relaxed text-balance text-gray-500">
Trabaja más rápido que nunca con nuestros atajos de teclado
</p>
</div>
</div>

Como puedes usar cualquier background-image como máscara, lo lógico era copiar los utilitarios bg-* para que compartieran la misma API. El problema con ese enfoque es que a menudo quieres combinar múltiples máscaras y los utilitarios bg-* no son componibles.

Así que en su lugar, creamos un nuevo conjunto de utilitarios para trabajar con mask-image que son componibles y diseñados específicamente para el caso de uso del enmascaramiento. Por ejemplo, puedes usar utilitarios como mask-b-from-<value> y mask-t-to-<value> para añadir una máscara de gradiente lineal a un solo lado de un elemento:

mask-t-from-50%

mask-r-from-30%

mask-l-from-50% mask-l-to-90%

mask-b-from-20% mask-b-to-80%

<div class="mask-t-from-50% bg-[url(/img/mountains.jpg)] ..."></div>
<div class="mask-r-from-30% bg-[url(/img/mountains.jpg)] ..."></div>
<div class="mask-l-from-50% mask-l-to-90% bg-[url(/img/mountains.jpg)] ..."></div>
<div class="mask-b-from-20% mask-b-to-80% bg-[url(/img/mountains.jpg)] ..."></div>

Es más natural pensar en qué lado quieres enmascarar, en lugar de intentar averiguar el gradiente exacto que necesitas usar.

Los utilitarios de máscara de gradiente también son componibles, por lo que puedes combinar gradientes radiales, cónicos y lineales para crear máscaras más complejas:

<div class="mask-b-from-50% mask-radial-[50%_90%] mask-radial-from-80% bg-[url(/img/mountains.jpg)] ..."></div>
<div class="mask-r-from-80% mask-b-from-80% mask-radial-from-70% mask-radial-to-85% bg-[url(/img/mountains.jpg)] ..."></div>

El enmascaramiento es una técnica superpoderosa y hay mucho más en la API de lo que podemos cubrir aquí. Para un desglose completo de los nuevos utilitarios, consulta la documentación.


Compatibilidad mejorada con navegadores antiguos

Nos volcamos de lleno en las características modernas de la plataforma con Tailwind CSS v4.0 para crear el mejor framework posible y darle a esta versión la mayor vida útil posible.

Desafortunadamente, algunas de esas características se degradan muy mal en navegadores antiguos, hasta el punto de que incluso cosas básicas como colores y sombras podrían no renderizarse en absoluto para alguien que visita desde un iPhone o iPad antiguo que está atascado en Safari 15.

Para Tailwind CSS v4.1, pusimos mucho esfuerzo en idear y probar nuestros propios fallbacks específicos del framework para hacer que tus sitios se rendericen lo mejor posible en navegadores antiguos, incluso si algunas cosas supermodernas todavía no se comportan exactamente igual.

Comparación entre cómo Tailwind CSS v4.0 (izquierda) y Tailwind CSS v4.1 (derecha) renderizan en Safari 15.5. Tailwind CSS v4.0 no logra renderizar algunos gradientes de fondo que ahora son visibles en Tailwind CSS v4.1

Aquí tienes una lista de las cosas que hemos logrado mejorar en esta versión:

  • Los colores definidos en oklab ahora se renderizan en versiones antiguas de Safari
  • Las características que dependen de propiedades personalizadas definidas con @property (como sombras, transformaciones, gradientes y más) ahora funcionan en versiones antiguas de Safari y Firefox
  • Los colores que usan el modificador de opacidad ahora se renderizan con fallbacks incorporados en navegadores antiguos
  • Los gradientes que usan métodos de interpolación explícitos recurren al valor predeterminado del navegador cuando no son compatibles

Tailwind CSS v4 todavía está diseñado para navegadores modernos como Safari 16.4 y superiores y todavía depende de muchas características modernas para que todo funcione perfectamente, pero al menos ahora tus sitios se renderizarán y serán utilizables en navegadores antiguos, incluso si en ciertas situaciones específicas el color de alguna sombra es diferente.

Para aprender todo lo que necesitas saber sobre la compatibilidad con navegadores en Tailwind CSS v4, puedes leer la documentación completa de compatibilidad con navegadores.


Ajuste fino del texto con overflow-wrap

Los nuevos utilitarios overflow-wrap te permiten controlar cómo se ajusta el texto dentro de un elemento. El utilitario wrap-break-word es especialmente útil para palabras largas o URLs que de otro modo podrían romper tu diseño:

La palabra más larga en cualquiera de los principales diccionarios del idioma inglés es pneumonoultramicroscopicsilicovolcanoconiosis, una palabra que se refiere a una enfermedad pulmonar contraída por la inhalación de partículas de sílice muy finas, específicamente de un volcán; médicamente, es lo mismo que la silicosis.

<p class="wrap-break-word">La palabra más larga en cualquiera de los principales...</p>

El único caso en el que esto no se comporta exactamente como esperarías es dentro de un contenedor flex y ahí es donde probablemente quieras usar el nuevo utilitario wrap-anywhere en su lugar.

Es similar a wrap-break-word, pero permite saltos de línea a mitad de palabra al calcular el tamaño intrínseco del elemento, reemplazando la necesidad de establecer min-width: 0 en el elemento hijo:

wrap-break-word

Jay Riemenschneider

jason.riemenschneider@vandelayindustries.com

wrap-anywhere

Jay Riemenschneider

jason.riemenschneider@vandelayindustries.com

<div class="flex max-w-sm">
<img class="size-16 rounded-full" src="/img/profile.jpg" />
<div class="wrap-break-word">
<p class="font-medium">Jay Riemenschneider</p>
<p>jason.riemenschneider@vandelayindustries.com</p>
</div>
</div>
<div class="flex max-w-sm">
<img class="size-16 rounded-full" src="/img/profile.jpg" />
<div class="wrap-anywhere">
<p class="font-medium">Jay Riemenschneider</p>
<p>jason.riemenschneider@vandelayindustries.com</p>
</div>
</div>

No hay mucho más que eso, pero aquí está la documentación de overflow-wrap si quieres leerla de nuevo con palabras ligeramente diferentes.


Soporte para drop-shadow coloreados

Mientras desarrollábamos el soporte para text-shadow, pensamos que también podríamos añadir otra característica que nunca llegamos a implementar: sombras paralelas coloreadas.

Ahora puedes usar utilitarios como drop-shadow-indigo-500 y drop-shadow-cyan-500/50 para cambiar el color de una sombra paralela:

drop-shadow-cyan-500/50

drop-shadow-sky-500/50

drop-shadow-indigo-500/50

<svg class="fill-cyan-500 drop-shadow-xl drop-shadow-cyan-500/50 ...">...</svg>
<svg class="fill-blue-500 drop-shadow-xl drop-shadow-blue-500/50 ...">...</svg>
<svg class="fill-indigo-500 drop-shadow-xl drop-shadow-indigo-500/50 ...">...</svg>

No hay mucho más, pero aquí está la documentación de drop-shadow de todos modos.


Apunta a dispositivos de entrada con pointer-* y any-pointer-*

Las nuevas variantes pointer-fine y pointer-coarse te permiten estilizar algo de manera diferente dependiendo de si el usuario está usando un dispositivo con ratón o una pantalla táctil.

Usa pointer-fine para apuntar a dispositivos de puntero precisos como ratones y trackpads, y pointer-coarse para apuntar a dispositivos de menor precisión como pantallas táctiles:

Intenta emular un dispositivo táctil en tus herramientas de desarrollador para ver los cambios

<fieldset aria-label="Elige una opción de memoria">
<div class="flex items-center justify-between">
<div>RAM</div>
<a href="#"> Ver especificaciones de rendimiento </a>
</div>
<div class="mt-4 grid grid-cols-6 gap-2 pointer-coarse:mt-6 pointer-coarse:grid-cols-3 pointer-coarse:gap-4">
<label class="p-2 pointer-coarse:p-4 ...">
<input type="radio" name="memory-option" value="4 GB" className="sr-only" />
<span>4 GB</span>
</label>
<!-- ... -->
</div>
</fieldset>

Si estás en tu teléfono, verás los estilos pointer-coarse aplicados, que hacen que los objetivos táctiles sean más grandes y fáciles de pulsar. Si estás en un escritorio, verás los estilos pointer-fine aplicados, que hacen que los objetivos táctiles sean más pequeños y precisos.

Las variantes any-pointer-* funcionan de la misma manera, pero en lugar de solo verificar el dispositivo de puntero principal del usuario, verifican si cualquier dispositivo de puntero coincide. Así que any-pointer-coarse coincidirá en una laptop con pantalla táctil, por ejemplo, incluso si el usuario también tiene un ratón conectado.


Alinea elementos a la última línea base

Al trabajar con diseños flex o grid, a veces necesitas alinear algo a la línea base de la última línea de texto en lugar del final del contenedor.

El nuevo utilitario items-baseline-last hace precisamente eso:

Spencer Sharp

Trabajando en el futuro del reclutamiento de astronautas en Space Recruit.

spacerecruit.com
Alex Reed

Un diseñador multidisciplinario.

alex-reed.com
<div class="grid grid-cols-[1fr_auto] items-baseline-last">
<div>
<img src="img/spencer-sharp.jpg" />
<h4>Spencer Sharp</h4>
<p>Trabajando en el futuro del reclutamiento de astronautas en Space Recruit.</p>
</div>
<p>spacerecruit.com</p>
</div>

También hemos añadido self-baseline-last para cuando necesites alinear solo un elemento individual, y no todos los elementos en el contenedor flex o grid.


Mantén el contenido visible con alineación safe

¿Alguna vez has tenido contenido centrado que se desborda en ambas direcciones cuando el contenedor se hace demasiado pequeño? Ahora no tienes que usar una container query para cambiar la alineación en diferentes tamaños.

Los nuevos utilitarios de alineación safe cambiarán la alineación a start cuando el contenedor comience a desbordarse, para que solo se desborde en una dirección.

Redimensiona el contenedor para ver el comportamiento de la alineación

justify-center

  • Ventas
  • Marketing
  • SEO
  • Analítica
  • Diseño
  • Estrategia
  • Crecimiento
  • UX/UI

justify-center-safe

  • Ventas
  • Marketing
  • SEO
  • Analítica
  • Diseño
  • Estrategia
  • Crecimiento
  • UX/UI
justify-center
<ul class="flex justify-center gap-2 ...">
<li>Ventas</li>
<li>Marketing</li>
<li>SEO</li>
<!-- ... -->
</ul>
justify-center-safe
<ul class="flex justify-center-safe gap-2 ...">
<li>Ventas</li>
<li>Marketing</li>
<li>SEO</li>
<!-- ... -->
</ul>

Estos utilitarios funcionan tanto con flexbox como con grid layouts, y están disponibles para todas las propiedades de alineación.


Ignora rutas específicas con @source not

A veces necesitas excluir específicamente algunas partes de tu base de código para que no sean escaneadas por Tailwind. Ahora puedes usar @source not para ignorar rutas específicas al escanear en busca de nombres de clase:

CSS
@import "tailwindcss";
@source not "./src/components/legacy";

Esto es útil cuando tienes un gran número de archivos en tu proyecto, pero solo quieres escanear un subconjunto específico de ellos.


Incluye en lista segura utilitarios específicos con @source inline(…)

Si necesitas asegurarte de que Tailwind genere ciertos nombres de clase que no existen en tus archivos de contenido, puedes forzar su generación usando @source inline():

CSS
@import "tailwindcss";
@source inline("underline");
CSS generado
.underline {
text-decoration: underline;
}

Esto es el equivalente a la opción de configuración safelist en versiones anteriores de Tailwind, pero ahora puedes usarlo en tus archivos CSS en lugar de tu archivo de configuración.

La entrada de origen es expandida por llaves, por lo que puedes generar múltiples clases a la vez. Por ejemplo, para generar todos los tonos de rojo con variantes hover, puedes añadir un rango a la entrada de origen:

CSS
@import "tailwindcss";
@source inline("{hover:,}bg-red-{50,{100..900..100},950}");
CSS generado
.bg-red-50 {
background-color: var(--color-red-50);
}
.bg-red-100 {
background-color: var(--color-red-100);
}
.bg-red-200 {
background-color: var(--color-red-200);
}
/* ... */
.bg-red-800 {
background-color: var(--color-red-800);
}
.bg-red-900 {
background-color: var(--color-red-900);
}
.bg-red-950 {
background-color: var(--color-red-950);
}
@media (hover: hover) {
.hover\:bg-red-50:hover {
background-color: var(--color-red-50);
}
/* ... */
.hover\:bg-red-950:hover {
background-color: var(--color-red-950);
}
}

Esto generará tonos de rojo del 100 al 900 en incrementos de 100, así como los tonos 50 y 950. También añade la variante hover: para cada una de esas clases.

También puedes usar @source inline() con el modificador not para excluir clases específicas de ser generadas:

CSS
@import "tailwindcss";
@source not inline("container");

Esto evitará específicamente que se genere la clase container, incluso si la palabra container se detecta en tus archivos fuente.

Para más detalles, consulta la documentación de detección de clases en archivos fuente.


Un montón de otras nuevas variantes

Acordeones más bonitos con details-content

Aunque siempre pudiste añadir estilos a los hijos de un elemento <details>, ha sido imposible estilizar el contenedor de contenido en sí mismo.

La nueva variante details-content apunta al contenedor de contenido, lo cual es útil para posicionar el contenedor de contenido en relación con el elemento <summary>:

¿Por qué lo llaman Ovaltine?

La taza es redonda. El frasco es redondo. Deberían llamarlo Roundtine.

<details class="rounded-lg border border-transparent p-6 details-content:mt-3 details-content:-ml-0.5" open>
<summary class="text-sm leading-6 font-semibold text-gray-900 select-none dark:text-white">
¿Por qué lo llaman Ovaltine?
</summary>
<div class="border-gray-200 bg-gray-50 py-3 pl-3 dark:border-white/10 dark:bg-gray-800/50 ...">
<p>La taza es redonda. El frasco es redondo. Deberían llamarlo Roundtine.</p>
</div>
</details>

Apunta al modo inverted-colors

Usa la variante inverted-colors para añadir estilos condicionalmente cuando el usuario ha habilitado un esquema de colores invertidos en su SO:

<div class="shadow-xl inverted-colors:shadow-none ...">
<!-- ... -->
</div>

Esto es útil para cosas como evitar que las sombras negras se vuelvan blancas cuando se habilitan los colores invertidos.


Nueva variante noscript

Sí, algunas personas desactivan JavaScript y ahora puedes decirles que tu aplicación no funciona sin él. La variante noscript te permite aplicar estilos condicionalmente cuando JS está desactivado:

<div class="hidden noscript:block">Por favor, habilita JavaScript para usar esta aplicación.</div>

Ya podías hacer esto con la etiqueta <noscript>, pero ahora también puedes hacerlo con CSS, que Tailwind te permite escribir en tu HTML, así que... sí.


Mejor validación de formularios con user-valid y user-invalid

Ever tried the :invalid pseudo-class only for the page to be full of red invalid states as soon as it loads, before the user has even touched your form?

The new user-valid and user-invalid variants try to solve this problem, by only applying validation-related styling after the user has actually interacted with the controls:

<input required class="border user-valid:border-green-500" />
<input required class="border user-invalid:border-red-500" />

¡Así que eso es todo, eso es Tailwind CSS v4.1! Actualiza a la última versión usando npm y empieza a jugar con ella hoy mismo:

Usando la CLI de Tailwind
npm install tailwindcss@latest @tailwindcss/cli@latest
Usando Vite
npm install tailwindcss@latest @tailwindcss/vite@latest
Usando PostCSS
npm install tailwindcss@latest @tailwindcss/postcss@latest

¡Esperamos ver lo que construyes con las nuevas características!

Recibe todas nuestras actualizaciones directamente en tu bandeja de entrada.
Suscríbete a nuestro boletín.

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