Tailwind CSS v3.4: Unidades dinámicas de viewport, soporte :has(), titulares equilibrados, subgrid y más

Adam Wathan
Tailwind CSS v3.4

No hay nada como construir un nuevo producto importante para encontrar todas las características que desearías tener en tus propias herramientas, así que aprovechamos parte de esa inspiración y la convertimos en esto — Tailwind CSS v3.4.

Como siempre, las mejoras van desde cosas por las que has estado enojado durante años, hasta soportar características CSS de las que nunca has oído hablar y probablemente ni siquiera puedas usar en el trabajo.

Todo lo bueno está en esa lista, pero echa un vistazo a las notas de la versión para un par de detalles más que no fueron lo suficientemente emocionantes como para ganarse un lugar en esta publicación.

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

npm install tailwindcss@latest

O prueba todas las nuevas características en Tailwind Play, directamente en tu navegador.


Unidades dinámicas de viewport

Cuando se agregó la unidad vh a los navegadores, todos nos emocionamos mucho — ¡finalmente una forma de construir layouts de aplicación de altura completa y cosas así sin perforar height: 100% a través de 17 capas de DOM! Pero los dispositivos móviles y sus malditas barras de menú que desaparecen arruinaron toda la diversión, haciendo efectivamente que la unidad vh fuera solo un cruel recordatorio de un futuro que podría haber sido tan genial.

Bueno, ahora tenemos un nuevo futuro — dvh, lvh, y svh están diseñados para acomodar ese cromo del navegador que desaparece y Tailwind CSS v3.4 los soporta de forma predeterminada:

Desplázate hacia arriba y abajo en el viewport para ocultar/mostrar la UI del navegador

tailwindcss.com

h-dvh

<div class="h-dvh">
<!-- ... -->
</div>

Hemos agregado las siguientes nuevas clases por defecto:

ClaseCSS
h-svhheight: 100svh
h-lvhheight: 100lvh
h-dvhheight: 100dvh
min-h-svhmin-height: 100svh
min-h-lvhmin-height: 100lvh
min-h-dvhmin-height: 100dvh
max-h-svhmax-height: 100svh
max-h-lvhmax-height: 100lvh
max-h-dvhmax-height: 100dvh

Si necesitas otros valores, siempre puedes usar valores arbitrarios también como min-h-[75dvh].

El soporte de navegadores es bastante bueno para estos hoy en día, así que a menos que necesites soportar Safari 14 puedes empezar a usarlos de inmediato.


Nueva variante :has()

La pseudo-clase :has() es lo más poderoso que se ha agregado a CSS desde flexbox. Por primera vez, puedes estilizar un elemento basándote en sus hijos, no solo en sus padres. Incluso hace posible estilizar basándose en hermanos posteriores.

Aquí hay un ejemplo donde el padre obtiene un anillo de color si el botón de radio dentro de él está marcado:

Método de pago
<label class="has-[:checked]:bg-indigo-50 has-[:checked]:text-indigo-900 has-[:checked]:ring-indigo-500 ...">
<svg fill="currentColor">
<!-- ... -->
</svg>
Google Pay
<input type="radio" class="accent-indigo-500 ..." />
</label>

Siento que he encontrado un nuevo caso de uso para :has() cada semana mientras trabajaba en este nuevo kit de UI que hemos estado construyendo durante los últimos meses, y ha reemplazado una cantidad loca de JavaScript en nuestro código.

Por ejemplo, nuestros inputs de texto son bastante complicados en cuanto a diseño y requieren un pequeño elemento contenedor para construir. Sin :has(), no teníamos forma de estilizar el contenedor basándonos en cosas como el estado :disabled del input, pero ahora podemos:

input.jsx
export function Input({ ... }) {
return (
<span className="has-[:disabled]:opacity-50 ...">
<input ... />
</span>
)
}

Este es bastante vanguardista pero, literalmente a partir de hoy, ya es compatible con la última versión de todos los principales navegadores. Dale unas semanas para que cualquier usuario de Firefox instale la actualización de hoy y deberíamos poder volvernos locos con él.


Estiliza hijos con la variante *

Aquí hay una que la gente ha querido literalmente desde siempre — una forma de estilizar hijos desde el padre usando clases de utilidad.

Hemos agregado una nueva variante * que apunta a hijos directos, permitiéndote hacer cosas como esta:

Categorías

Ventas
Marketing
SEO
Analítica
Diseño
Estrategia
Seguridad
Crecimiento
Móvil
UX/UI
<div>
<h2>Categorías:<h2>
<ul class="*:rounded-full *:border *:border-sky-100 *:bg-sky-50 *:px-2 *:py-0.5 dark:text-sky-300 dark:*:border-sky-500/15 dark:*:bg-sky-500/10 ...">
<li>Ventas</li>
<li>Marketing</li>
<li>SEO</li>
<!-- ... -->
</ul>
</div>

Generalmente recomendaría simplemente estilizar los hijos directamente, but esto puede ser útil cuando no controlas esos elementos o necesitas hacer un ajuste condicional debido al contexto en el que se usa el elemento.

También se puede componer con otras variantes, por ejemplo hover:*:underline estilizará cualquier hijo cuando el hijo esté en hover.

Aquí hay una forma genial en que estamos usando eso para agregar condicionalmente estilos de layout a diferentes elementos hijos en el nuevo kit de UI en el que estamos trabajando:

JSX
function Field({ children }) {
return (
<div className="data-[slot=description]:*:mt-4 ...">
{children}
</div>
)
}
function Description({ children }) {
return (
<p data-slot="description" ...>{children}</p>
)
}
function Example() {
return (
<Field>
<Label>First name</Label>
<Input />
<Description>Please tell me you know your own name.</Description>
</Field>
)
}

¿Ves esa loca clase data-[slot=description]:*:mt-4? Primero apunta a todos los hijos directos (esa es la parte *:), luego los filtra a solo los elementos con un atributo data-slot="description" usando data-[slot=description].

Esto facilita apuntar solo a hijos específicos, sin tener que bajar hasta una variante arbitraria cruda.

Esperando ver todas las cosas horribles que todos harán para hacerme arrepentir de agregar esta característica.


Nuevas utilidades size-*

Estás harto de escribir h-5 w-5 cada vez que necesitas dimensionar un avatar, tú lo sabes y yo lo sé.

En Tailwind CSS v3.4 finalmente hemos agregado una nueva utilidad size-* que establece width y height al mismo tiempo:

HTML
<div>
<img class="h-10 w-10" ...>
<img class="h-12 w-12" ...>
<img class="h-14 w-14" ...>
<img class="size-10" ...>
<img class="size-12" ...>
<img class="size-14" ...>
</div>

Hemos querido agregar esto desde siempre, pero siempre nos hemos atascado en el nombre exacto — size-* parecía mucho para escribir en comparación con w-* o h-* y s-* parecía demasiado críptico.

Después de usarlo durante unas semanas, sin embargo, puedo decir decisivamente que incluso con el nombre más largo, es mucho mejor que utilidades separadas de width y height. Súper conveniente, especialmente si lo combinas con variantes o usas un valor arbitrario complejo.


Titulares equilibrados con utilidades text-wrap

¿Cuánto tiempo has pasado jugueteando con max-width o insertando saltos de línea responsivos para intentar que esos pequeños encabezados de sección se ajusten bien en tus páginas de destino? Bueno, ahora puedes dedicarle cero tiempo, porque el navegador puede hacerlo por ti con text-wrap: balance:

Amado puesto de sopa de Manhattan cierra

Los neoyorquinos enfrentan el frío invernal con menos calidez este año ya que el puesto de sopa más venerado de la ciudad cierra inesperadamente, tras una serie de eventos que han dejado perpleja a la comunidad.

<article>
<h3 class="text-balance ...">Amado puesto de sopa de Manhattan cierra<h3>
<p>Los neoyorquinos enfrentan el frío invernal...</p>
</article>

También hemos agregado text-pretty que intenta evitar palabras huérfanas al final de los párrafos usando text-wrap: pretty:

Amado puesto de sopa de Manhattan cierra

Los neoyorquinos enfrentan el frío invernal con menos calidez este año ya que el puesto de sopa más venerado de la ciudad cierra inesperadamente, tras una serie de eventos que han dejado perpleja a la comunidad.

<article class="text-pretty ...">
<h3>Amado puesto de sopa de Manhattan cierra<h3>
<p>Los neoyorquinos enfrentan el frío invernal...</p>
</article>

Lo bueno de estas características es que incluso si alguien visita tu sitio con un navegador más antiguo, simplemente recurrirán al comportamiento de ajuste regular, por lo que es totalmente seguro empezar a usarlas hoy.


Soporte Subgrid

Subgrid es una característica CSS bastante reciente que permite a un elemento heredar las columnas o filas de la cuadrícula de su padre, haciendo posible colocar sus elementos hijos en la cuadrícula padre.

HTML
<div class="grid grid-cols-4 gap-4">
<!-- ... -->
<div class="col-span-3 grid grid-cols-subgrid gap-4">
<div class="col-start-2">06</div>
</div>
<!-- ... -->
</div>

Estamos usando subgrid en el nuevo kit de UI en el que estamos trabajando, por ejemplo en menús desplegables, para que si algún elemento tiene un icono, todos los demás elementos se sangren para mantener el texto alineado:

HTML
<div role="menu" class="grid grid-cols-[auto_1fr]">
<a href="#" class="col-span-2 grid-cols-subgrid">
<svg class="mr-2">...</svg>
<span class="col-start-2">Cuenta</span>
</a>
<a href="#" class="col-span-2 grid-cols-subgrid">
<svg class="mr-2">...</svg>
<span class="col-start-2">Configuración</span>
</a>
<a href="#" class="col-span-2 grid-cols-subgrid">
<span class="col-start-2">Cerrar sesión</span>
</a>
</div>

Cuando ninguno de los elementos tiene un icono, la primera columna se encoge a 0px y el texto se alinea completamente a la izquierda.

Echa un vistazo a la documentación de MDN sobre subgrid para una introducción completa — es una característica un poco difícil de entender al principio, pero una vez que hace clic es un cambio de juego.


Escalas extendidas de min-width, max-width y min-height

Finalmente hemos extendido las escalas min-width, max-width, y min-height para incluir la escala completa de espaciado, por lo que clases como min-w-12 son realmente algo ahora:

HTML
<div class="min-w-12">
<!-- ... -->
</div>

Deberíamos haber hecho esto para v3.0 pero nunca llegamos a hacerlo — lo siento y de nada.


Escala de opacidad extendida

También hemos extendido la escala de opacidad para incluir cada paso de 5 de forma predeterminada:

HTML
<div class="opacity-35">
<!-- ... -->
</div>

Esperemos que eso signifique unos pocos valores arbitrarios menos en tu marcado. Voy por ti después 2.5%.


Escala grid-rows-* extendida

También hemos aumentado el número incorporado de filas de grid de 6 a 12 porque por qué no:

HTML
<div class="grid grid-rows-9">
<!-- ... -->
</div>

Tal vez nos volvamos aún más locos y lo subamos a 16 en el próximo lanzamiento.


Nueva variante forced-colors

¿Alguna vez has oído hablar del modo forced colors? Tu sitio probablemente se ve bastante mal en él.

Bueno, ahora al menos no puedes culparnos, porque Tailwind CSS v3.4 incluye una variante forced-colors para ajustar estilos para el modo forced colors:

HTML
<form>
<input type="checkbox" class="appearance-none forced-colors:appearance-auto ..." />
</form>

Es realmente útil para ajustar finamente controles totalmente personalizados, especialmente combinado con valores arbitrarios y un conocimiento práctico de los colores del sistema CSS.


Nuevas utilidades forced-color-adjust

También hemos agregado nuevas utilidades forced-color-adjust-auto y forces-color-adjust-none para controlar cómo afecta el modo forced colors a tu diseño:

HTML
<fieldset>
<legend>Elige un color</legend>
<div class="forced-color-adjust-none ...">
<label>
<input class="sr-only" type="radio" name="color-choice" value="white" />
<span class="sr-only">Blanco</span>
<span class="size-6 rounded-full bg-white"></span>
</label>
<label>
<input class="sr-only" type="radio" name="color-choice" value="gray" />
<span class="sr-only">Gris</span>
<span class="size-6 rounded-full bg-gray-300"></span>
</label>
<!-- ... -->
</div>
</fieldset>

Estas deben usarse con bastante moderación, pero pueden ser útiles cuando es crítico que algo se renderice en un color específico sin importar qué, como elegir el color de algo que alguien está comprando en una tienda en línea.

Para aprender más sobre todo esto de forced colors, recomiendo leer "Forced colors explicado: Una guía práctica" en el blog de Polypane — de lejos la publicación más útil que he encontrado sobre este tema.


Si has estado prestando mucha atención, quizás te estés preguntando sobre Oxide, las mejoras del motor que previsualizamos en Tailwind Connect este verano.

Originalmente habíamos programado esas mejoras para v3.4, pero todavía tenemos algunas cosas que pulir y tantas de estas otras mejoras se habían acumulado que sentimos que tenía sentido sacarlo todo en lugar de retenerlo. Lo de Oxide todavía está por llegar, y será la mejora principal para el próximo lanzamiento de Tailwind CSS en el nuevo año.

Mientras tanto, profundiza en Tailwind CSS v3.4 actualizando a la última versión con npm:

$ npm install tailwindcss@latest

Con :has() y la nueva variante *, tu HTML está a punto de descontrolarse más que nunca.

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