Conceptos clave
Uso de utilidades para estilizar elementos al pasar el cursor (hover), enfocar (focus) y más.
Cada clase de utilidad en Tailwind se puede aplicar de forma condicional agregando una variante al comienzo del nombre de la clase que describa la condición a la que deseas apuntar.
Por ejemplo, para aplicar la clase bg-sky-700 al pasar el cursor (hover), usa la clase hover:bg-sky-700:
Pasa el cursor sobre este botón para ver cambiar el color de fondo
<button class="bg-sky-500 hover:bg-sky-700 ...">Guardar cambios</button>Al escribir CSS de la manera tradicional, un solo nombre de clase haría cosas diferentes según el estado actual:
Tradicionalmente, el mismo nombre de clase aplica diferentes estilos al pasar el cursor (hover)
.btn-primary { background-color: #0ea5e9;}.btn-primary:hover { background-color: #0369a1;}En Tailwind, en lugar de agregar los estilos para un estado hover a una clase existente, agregas otra clase al elemento que solo hace algo al pasar el cursor (hover):
En Tailwind, se usan clases separadas para el estado predeterminado y el estado hover
.bg-sky-500 { background-color: #0ea5e9;}.hover\:bg-sky-700:hover { background-color: #0369a1;}¿Notas cómo hover:bg-sky-700 solo define estilos para el estado :hover? No hace nada de forma predeterminada, pero tan pronto como pasas el cursor sobre un elemento con esa clase, el color de fondo cambiará a sky-700.
A esto nos referimos cuando decimos que una clase de utilidad se puede aplicar de forma condicional; al usar variantes, puedes controlar exactamente cómo se comporta tu diseño en diferentes estados, sin salir nunca de tu HTML.
Tailwind incluye variantes para casi todo lo que necesites, incluyendo:
:hover, :focus, :first-child y :required::before, ::after, ::placeholder y ::selectionprefers-reduced-motion[dir="rtl"] y [open]& > * y & *Estas variantes incluso se pueden apilar para apuntar a situaciones más específicas, por ejemplo, cambiar el color de fondo en modo oscuro, en el punto de ruptura mediano, al pasar el cursor:
<button class="dark:md:hover:bg-fuchsia-600 ...">Guardar cambios</button>En esta guía aprenderás sobre cada variante disponible en el framework, cómo usarlas con tus propias clases personalizadas e incluso cómo crear las tuyas propias.
Estiliza elementos al pasar el cursor (hover), enfocar (focus) y activar (active) usando las variantes hover, focus y active:
Intenta interactuar con este botón para ver los estados hover, focus y active
<button class="bg-violet-500 hover:bg-violet-600 focus:outline-2 focus:outline-offset-2 focus:outline-violet-500 active:bg-violet-700 ..."> Guardar cambios</button>Tailwind también incluye variantes para otros estados interactivos como :visited, :focus-within, :focus-visible y más.
Consulta la referencia de pseudoclases para obtener una lista completa de las variantes de pseudoclases disponibles.
Estiliza un elemento cuando sea el primer hijo (first-child) o el último hijo (last-child) usando las variantes first y last:
Kristen Ramos
kristen.ramos@example.com
Floyd Miles
floyd.miles@example.com
Courtney Henry
courtney.henry@example.com
Ted Fox
ted.fox@example.com
<ul role="list"> {#each people as person} <!-- Elimina el padding superior/inferior cuando es el primer/último hijo --> <li class="flex py-4 first:pt-0 last:pb-0"> <img class="h-10 w-10 rounded-full" src={person.imageUrl} alt="" /> <div class="ml-3 overflow-hidden"> <p class="text-sm font-medium text-gray-900 dark:text-white">{person.name}</p> <p class="truncate text-sm text-gray-500 dark:text-gray-400">{person.email}</p> </div> </li> {/each}</ul>También puedes estilizar un elemento cuando es un hijo impar (odd) o par (even) usando las variantes odd y even:
| Nombre | Título | Correo electrónico |
|---|---|---|
| Jane Cooper | Técnico de Paradigma Regional | jane.cooper@example.com |
| Cody Fisher | Oficial de Directivas de Producto | cody.fisher@example.com |
| Leonard Krasner | Diseñador Senior | leonard.krasner@example.com |
| Emily Selman | Vicepresidente de Ingeniería de Hardware | emily.selman@example.com |
| Anna Roberts | Director de Estrategia | anna.roberts@example.com |
<table> <!-- ... --> <tbody> {#each people as person} <!-- Usa diferentes colores de fondo para filas impares y pares --> <tr class="odd:bg-white even:bg-gray-50 dark:odd:bg-gray-900/50 dark:even:bg-gray-950"> <td>{person.name}</td> <td>{person.title}</td> <td>{person.email}</td> </tr> {/each} </tbody></table>Usa las variantes nth-* y nth-last-* para estilizar elementos secundarios según su posición en la lista:
<div class="nth-3:underline"> <!-- ... --></div><div class="nth-last-5:underline"> <!-- ... --></div><div class="nth-of-type-4:underline"> <!-- ... --></div><div class="nth-last-of-type-6:underline"> <!-- ... --></div>Puedes pasar cualquier número que desees a estos de forma predeterminada, y usar valores arbitrarios para expresiones más complejas como nth-[2n+1_of_li].
Tailwind también incluye variantes para otras pseudoclases estructurales como :only-child, :first-of-type, :empty y más.
Consulta la referencia de pseudoclases para obtener una lista completa de las variantes de pseudoclases disponibles.
Estiliza elementos de formulario en diferentes estados usando variantes como required, invalid y disabled:
Intenta hacer que la dirección de correo electrónico sea válida para ver cambiar los estilos
<input type="text" value="tbone" disabled class="invalid:border-pink-500 invalid:text-pink-600 focus:border-sky-500 focus:outline focus:outline-sky-500 focus:invalid:border-pink-500 focus:invalid:outline-pink-500 disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500 disabled:shadow-none dark:disabled:border-gray-700 dark:disabled:bg-gray-800/20 ..."/>El uso de variantes para este tipo de cosas puede reducir la cantidad de lógica condicional en tus plantillas, permitiéndote usar el mismo conjunto de clases independientemente del estado en que se encuentre una entrada y dejando que el navegador aplique los estilos correctos por ti.
Tailwind también incluye variantes para otros estados de formulario como :read-only, :indeterminate, :checked y más.
Consulta la referencia de pseudoclases para obtener una lista completa de las variantes de pseudoclases disponibles.
Usa la variante has-* para estilizar un elemento según el estado o el contenido de sus descendientes:
<label class="has-checked:bg-indigo-50 has-checked:text-indigo-900 has-checked:ring-indigo-200 dark:has-checked:bg-indigo-950 dark:has-checked:text-indigo-200 dark:has-checked:ring-indigo-900 ..."> <svg fill="currentColor"> <!-- ... --> </svg> Google Pay <input type="radio" class="checked:border-indigo-500 ..." /></label>Puedes usar has-* con una pseudoclase, como has-[:focus], para estilizar un elemento según el estado de sus descendientes. También puedes usar selectores de elementos, como has-[img] o has-[a], para estilizar un elemento según el contenido de sus descendientes.
Si necesitas estilizar un elemento según los descendientes de un elemento padre, puedes marcar al padre con la clase group y usar la variante group-has-* para estilizar el elemento de destino:
Simplemente feliz de estar aquí.
Un diseñador multidisciplinario, trabajando en la intersección del arte y la tecnología.
alex-reed.com
Empujando píxeles. Lanzando divs.
<div class="group ..."> <img src="..." /> <h4>Spencer Sharp</h4> <svg class="hidden group-has-[a]:block ..."><!-- ... --></svg> <p>Diseñador de Productos en <a href="...">planeteria.tech</a></p></div>Si necesitas estilizar un elemento según los descendientes de un elemento hermano, puedes marcar al hermano con la clase peer y usar la variante peer-has-* para estilizar el elemento de destino:
<div> <label class="peer ..."> <input type="checkbox" name="todo[1]" checked /> Crear una lista de tareas pendientes </label> <svg class="peer-has-checked:hidden ..."><!-- ... --></svg></div>Usa la variante not- para estilizar un elemento cuando una condición no es verdadera.
Es particularmente potente cuando se combina con otras variantes de pseudoclases, por ejemplo, combinando not-focus: con hover: para aplicar únicamente estilos hover cuando un elemento no está enfocado:
Intenta enfocar el botón y luego pasar el cursor sobre él
<button class="bg-indigo-600 hover:not-focus:bg-indigo-700"> <!-- ... --></button>También puedes combinar la variante not- con variantes de consultas de medios como forced-colors o supports para estilizar un elemento únicamente cuando algo en el entorno del usuario no es verdadero:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>Cuando necesites estilizar un elemento según el estado de algún elemento padre, marca al padre con la clase group y usa variantes group-* como group-hover para estilizar el elemento de destino:
Pasa el cursor sobre la tarjeta para ver ambos elementos de texto cambiar de color
<a href="#" class="group ..."> <div> <svg class="stroke-sky-500 group-hover:stroke-white ..." fill="none" viewBox="0 0 24 24"> <!-- ... --> </svg> <h3 class="text-gray-900 group-hover:text-white ...">Nuevo proyecto</h3> </div> <p class="text-gray-500 group-hover:text-white ...">Crea a nuevo proyecto a partir de una variedad de plantillas iniciales.</p></a>Este patrón funciona con cada variante de pseudoclase, por ejemplo group-focus, group-active o incluso group-odd.
Al anidar grupos, puedes estilizar algo basado en el estado de un grupo padre específico asignándole a ese padre un nombre de grupo único con una clase group/{name}, e incluyendo ese nombre en variantes usando clases como group-hover/{name}:
<ul role="list"> {#each people as person} <li class="group/item ..."> <!-- ... --> <a class="group/edit invisible group-hover/item:visible ..." href="tel:{person.phone}"> <span class="group-hover/edit:text-gray-700 ...">Llamar</span> <svg class="group-hover/edit:translate-x-0.5 group-hover/edit:text-gray-500 ..."><!-- ... --></svg> </a> </li> {/each}</ul>Los grupos pueden nombrarse como desees y no necesitan ser configurados de ninguna manera; simplemente nombra tus grupos directamente en tu marcado y Tailwind generará automáticamente el CSS necesario.
Puedes crear variantes group-* únicas sobre la marcha proporcionando tu propio selector como un valor arbitrario entre corchetes:
<div class="group is-published"> <div class="hidden group-[.is-published]:block"> Publicado </div></div>Para un mayor control, puedes usar el carácter & para marcar dónde debería terminar .group en el selector final en relación con el selector que estás pasando:
<div class="group"> <div class="group-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>La variante in-* funciona de manera similar a group, excepto que no necesitas agregar group al elemento padre:
<div tabindex="0" class="group"> <div class="opacity-50 group-focus:opacity-100"><div tabindex="0"> <div class="opacity-50 in-focus:opacity-100"> <!-- ... --> </div></div>La variante in-* responde a los cambios de estado en cualquier padre, por lo que si deseas un control más detallado deberás usar group en su lugar.
Cuando necesites estilizar un elemento según el estado de un elemento hermano (sibling), marca al hermano con la clase peer y usa variantes peer-* como peer-invalid para estilizar el elemento de destino:
Intenta hacer que la dirección de correo electrónico sea válida para ver desaparecer la advertencia
<form> <label class="block"> <span class="...">Correo electrónico</span> <input type="email" class="peer ..." /> <p class="invisible peer-invalid:visible ...">Por favor, proporciona una dirección de correo electrónico válida.</p> </label></form>Esto hace posible realizar todo tipo de trucos ingeniosos, como etiquetas flotantes, por ejemplo, sin nada de JS.
Este patrón funciona con cada variante de pseudoclase, por ejemplo peer-focus, peer-required y peer-disabled.
Es importante tener en cuenta que el marcador peer solo se puede usar en hermanos anteriores debido a cómo funciona el combinador de hermanos siguientes en CSS:
No funcionará, solo los hermanos anteriores pueden ser marcados como peers
<label> <span class="peer-invalid:text-red-500 ...">Correo electrónico</span> <input type="email" class="peer ..." /></label>Al usar múltiples peers, puedes estilizar algo según el estado de un peer específico asignándole a ese peer un nombre único con una clase peer/{name}, e incluyendo ese nombre en variantes usando clases como peer-checked/{name}:
<fieldset> <legend>Estado de publicación</legend> <input id="draft" class="peer/draft" type="radio" name="status" checked /> <label for="draft" class="peer-checked/draft:text-sky-500">Borrador</label> <input id="published" class="peer/published" type="radio" name="status" /> <label for="published" class="peer-checked/published:text-sky-500">Publicado</label> <div class="hidden peer-checked/draft:block">Los borradores solo son visibles para los administradores.</div> <div class="hidden peer-checked/published:block">Tu publicación será visible públicamente en tu sitio.</div></fieldset>Los peers pueden nombrarse como desees y no necesitan ser configurados de ninguna manera; simplemente nombra tus peers directamente en tu marcado y Tailwind generará automáticamente el CSS necesario.
Puedes crear variantes peer-* únicas sobre la marcha proporcionando tu propio selector como un valor arbitrario entre corchetes:
<form> <label for="email">Correo electrónico:</label> <input id="email" name="email" type="email" class="is-dirty peer" required /> <div class="peer-[.is-dirty]:peer-required:block hidden">Este campo es obligatorio.</div> <!-- ... --></form>Para un mayor control, puedes usar el carácter & para marcar dónde debería terminar .peer en el selector final en relación con el selector que estás pasando:
<div> <input type="text" class="peer" /> <div class="hidden peer-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>Estiliza los pseudoelementos ::before y ::after usando las variantes before y after:
<label> <span class="text-gray-700 after:ml-0.5 after:text-red-500 after:content-['*'] ...">Correo electrónico</span> <input type="email" name="email" class="..." placeholder="tu@ejemplo.com" /></label>Al usar estas variantes, Tailwind agregará automáticamente content: '' de forma predeterminada para que no tengas que especificarlo a menos que desees un valor diferente:
Cuando pareces molesto todo el tiempo, la gente piensa que estás ocupado.
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic dark:text-white"> Cuando pareces <span class="relative inline-block before:absolute before:-inset-1 before:block before:-skew-y-3 before:bg-pink-500"> <span class="relative text-white dark:text-gray-950">molesto</span> </span> todo el tiempo, la gente piensa que estás ocupado.</blockquote>Vale la pena señalar que realmente no necesitas los pseudoelementos ::before y ::after para la mayoría de las cosas en los proyectos de Tailwind; por lo general, es más sencillo usar un elemento HTML real.
Por ejemplo, aquí está el mismo diseño de arriba pero usando un <span> en lugar del pseudoelemento ::before, lo cual es un poco más fácil de leer y en realidad requiere menos código:
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic"> Cuando pareces <span class="relative"> <span class="absolute -inset-1 block -skew-y-3 bg-pink-500" aria-hidden="true"></span> <span class="relative text-white">molesto</span> </span> todo el tiempo, la gente piensa que estás ocupado.</blockquote>Reserva before y after para situaciones en las que sea importante que el contenido del pseudoelemento no esté realmente en el DOM y no pueda ser seleccionado por el usuario.
Estiliza el texto del marcador de posición (placeholder) de cualquier entrada (input) o área de texto (textarea) usando la variante placeholder:
<input class="placeholder:text-gray-500 placeholder:italic ..." placeholder="Buscar cualquier cosa..." type="text" name="search"/>Estiliza el botón en las entradas de tipo archivo (file inputs) usando la variante file:
<input type="file" class="file:mr-4 file:rounded-full file:border-0 file:bg-violet-50 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-violet-700 hover:file:bg-violet-100 dark:file:bg-violet-600 dark:file:text-violet-100 dark:hover:file:bg-violet-500 ..."/>Estiliza los contadores o viñetas en las listas usando la variante marker:
<ul role="list" class="list-disc marker:text-sky-400 ..."> <li>5 tazas de hongos Porcini picados</li> <li>1/2 taza de aceite de oliva</li> <li>3 libras de apio</li></ul>Hemos diseñado la variante marker para que sea heredable, por lo que aunque puedes usarla directamente en un elemento <li>, también puedes usarla en un padre para evitar repetirte.
Estiliza la selección de texto activa usando la variante selection:
Intenta seleccionar parte de este texto con el mouse
Así que empecé a caminar hacia el agua. No les voy a mentir muchachos, estaba aterrorizado. Pero seguí adelante, y a medida que avanzaba más allá de las olas, una extraña calma se apoderó de mí. No sé si fue intervención divina o la afinidad de todos los seres vivos, pero te digo Jerry, en ese momento, yo era un biólogo marino.
<div class="selection:bg-fuchsia-300 selection:text-fuchsia-900"> <p> Así que empecé a caminar hacia el agua. No les voy a mentir muchachos, estaba aterrorizado. Pero seguí adelante, y a medida que avanzaba más allá de las olas, una extraña calma se apoderó de mí. No sé si fue intervención divina o la afinidad de todos los seres vivos, pero te digo Jerry, en ese momento, yo <em>era</em> un biólogo marino. </p></div>Hemos diseñado la variante selection para que sea heredable, por lo que puedes agregarla en cualquier lugar del árbol y se aplicará a todos los elementos descendientes.
Esto facilita configurar el color de selección para que coincida con tu marca en todo tu sitio:
<html> <head> <!-- ... --> </head> <body class="selection:bg-pink-300"> <!-- ... --> </body></html>Estiliza la primera línea en un bloque de contenido usando la variante first-line, y la primera letra usando la variante first-letter:
Bueno, déjame decirte algo, chico divertido. ¿Sabes ese pequeño sello, el que dice "New York Public Library"? Bueno, puede que eso no signifique nada para ti, pero para mí significa mucho. Muchísimo.
Claro, adelante, ríete si quieres. He visto a tipos como tú antes: llamativos, haciéndose notar, alardeando de romper las normas. Sí, sé lo que estás pensando. ¿Por qué este tipo hace tanto alboroto por unos libros viejos de la biblioteca? Bueno, déjame darte una pista, jovencito.
<div class="text-gray-700"> <p class="first-letter:float-left first-letter:mr-3 first-letter:text-7xl first-letter:font-bold first-letter:text-gray-900 first-line:tracking-widest first-line:uppercase" > Bueno, déjame decirte algo, chico divertido. ¿Sabes ese pequeño sello, el que dice "New York Public Library"? </p> <p class="mt-6">Bueno, puede que eso no signifique nada para ti, pero para mí significa mucho. Muchísimo.</p></div>Estiliza el telón de fondo (backdrop) de un elemento <dialog> nativo usando la variante backdrop:
<dialog class="backdrop:bg-gray-50"> <form method="dialog"> <!-- ... --> </form></dialog>Si estás usando elementos <dialog> nativos en tu proyecto, es posible que también desees leer sobre cómo estilizar estados abiertos/cerrados usando la variante open.
Para estilizar un elemento en un punto de ruptura específico, usa variantes responsivas como md y lg.
Por ejemplo, esto renderizará una cuadrícula de 3 columnas en móviles, una cuadrícula de 4 columnas en pantallas de ancho medio y una cuadrícula de 6 columnas en pantallas de ancho grande:
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6"> <!-- ... --></div>Para estilizar un elemento según el ancho de un elemento padre en lugar de la ventana gráfica (viewport), usa variantes como @md y @lg:
<div class="@container"> <div class="flex flex-col @md:flex-row"> <!-- ... --> </div></div>Consulta la documentación de Diseño responsivo para ver en profundidad cómo funcionan estas características.
La consulta de medios prefers-color-scheme te indica si el usuario prefiere un tema claro o un tema oscuro, y generalmente se configura a nivel del sistema operativo.
Usa utilidades sin variante para apuntar al modo claro, y usa la variante dark para proporcionar anulaciones para el modo oscuro:
Modo claro
El bolígrafo Zero Gravity se puede usar para escribir en cualquier orientación, incluso al revés. Incluso funciona en el espacio exterior.
Modo oscuro
El bolígrafo Zero Gravity se puede usar para escribir en cualquier orientación, incluso al revés. Incluso funciona en el espacio exterior.
<div class="bg-white dark:bg-gray-900 ..."> <!-- ... --> <h3 class="text-gray-900 dark:text-white ...">Escribe al revés</h3> <p class="text-gray-500 dark:text-gray-400 ..."> El bolígrafo Zero Gravity se puede usar para escribir en cualquier orientación, incluso al revés. Incluso funciona en el espacio exterior. </p></div>Consulta la documentación de Modo oscuro para ver en profundidad cómo funciona esta característica.
La consulta de medios prefers-reduced-motion te indica si el usuario ha solicitado que minimices el movimiento no esencial.
Usa la variante motion-reduce para agregar estilos condicionalmente cuando el usuario haya solicitado un movimiento reducido:
Intenta emular `prefers-reduced-motion: reduce` en tus herramientas de desarrollador para ocultar el indicador de carga
<button type="button" class="bg-indigo-500 ..." disabled> <svg class="animate-spin motion-reduce:hidden ..." viewBox="0 0 24 24"><!-- ... --></svg> Procesando...</button>Tailwind también incluye una variante motion-safe que solo agrega estilos cuando el usuario no ha solicitado movimiento reducido. Esto puede ser útil cuando usar el ayudante motion-reduce implicaría tener que "deshacer" muchos estilos:
<!-- Usar `motion-reduce` puede significar tener que "deshacer" muchos estilos --><button class="transition hover:-translate-y-0.5 motion-reduce:transition-none motion-reduce:hover:translate-y-0 ..."> Guardar cambios</button><!-- Usar `motion-safe` requiere menos código en estas situaciones --><button class="motion-safe:transition motion-safe:hover:-translate-x-0.5 ...">Guardar cambios</button>La consulta de medios prefers-contrast te indica si el usuario ha solicitado más o menos contraste.
Usa la variante contrast-more para agregar estilos condicionalmente cuando el usuario haya solicitado más contraste:
Intenta emular `prefers-contrast: more` en tus herramientas de desarrollador para ver los cambios
<label class="block"> <span class="block text-sm font-medium text-gray-700">Número de Seguro Social</span> <input class="border-gray-200 placeholder-gray-400 contrast-more:border-gray-400 contrast-more:placeholder-gray-500 ..." /> <p class="text-gray-600 opacity-10 contrast-more:opacity-100 ...">Necesitamos esto para robar tu identidad.</p></label>Tailwind también incluye una variante contrast-less que puedes usar para agregar estilos condicionalmente cuando el usuario haya solicitado menos contraste.
La consulta de medios forced-colors indica si el usuario está utilizando un modo de colores forzados. Estos modos anulan los colores de tu sitio con una paleta definida por el usuario para texto, fondos, enlaces y botones.
Usa la variante forced-colors para agregar estilos condicionalmente cuando el usuario haya habilitado un modo de color forzado:
Intenta emular `forced-colors: active` en tus herramientas de desarrollador para ver los cambios
<label> <input type="radio" class="appearance-none forced-colors:appearance-auto" /> <p class="hidden forced-colors:block">Cian</p> <div class="bg-cyan-200 forced-colors:hidden ..."></div> <div class="bg-cyan-500 forced-colors:hidden ..."></div></label>Usa la variante not-forced-colors para aplicar estilos cuando el usuario no esté usando un modo de colores forzados:
<div class="not-forced-colors:appearance-none ..."> <!-- ... --></div>Tailwind también incluye utilidades de ajuste de colores forzados (forced color adjust) para optar por activar o desactivar los colores forzados.
Usa la variante inverted-colors para agregar estilos condicionalmente cuando el usuario haya habilitado un esquema de colores invertidos:
<div class="shadow-xl inverted-colors:shadow-none ..."> <!-- ... --></div>La consulta de medios pointer te indica si el usuario tiene un dispositivo de puntero principal, como un mouse, y la precisión de ese dispositivo de puntero.
Usa la variante pointer-fine para apuntar a un dispositivo de puntero preciso, como un mouse o trackpad, o la variante pointer-coarse para apuntar a un dispositivo de puntero menos preciso, como una pantalla táctil, lo cual puede ser útil para proporcionar objetivos de clic más grandes en dispositivos 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>Mientras que pointer solo apunta al dispositivo de puntero principal, any-pointer se usa para apuntar a cualquiera de los dispositivos de puntero que puedan estar disponibles. Usa las variantes any-pointer-fine y any-pointer-coarse para proporcionar estilos diferentes si al menos uno de los dispositivos de puntero conectados cumple con los criterios.
Puedes usar pointer-none y any-pointer-none para apuntar a la ausencia de un dispositivo de puntero.
Usa las variantes portrait y landscape para agregar estilos condicionalmente cuando la ventana gráfica (viewport) esté en una orientación específica:
<div> <div class="portrait:hidden"> <!-- ... --> </div> <div class="landscape:hidden"> <p>Esta experiencia está diseñada para verse en horizontal (landscape). Gira tu dispositivo para ver el sitio.</p> </div></div>Usa la variante noscript para agregar estilos condicionalmente según si el usuario tiene habilitado el scripting, como JavaScript:
<div class="hidden noscript:block"> <p>Esta experiencia requiere JavaScript para funcionar. Habilita JavaScript en la configuración de tu navegador.</p></div>Usa la variante print para agregar estilos condicionalmente que solo se aplican cuando se imprime el documento:
<div> <article class="print:hidden"> <h1>Mi receta secreta de pizza</h1> <p>Esta receta es un secreto y no se debe compartir con nadie</p> <!-- ... --> </article> <div class="hidden print:block">¿En serio estás intentando imprimir esto? ¡Es secreto!</div></div>Usa la variante supports-[...] para estilizar elementos según si una determinada característica es compatible con el navegador del usuario:
<div class="flex supports-[display:grid]:grid ..."> <!-- ... --></div>Bajo el capó, la variante supports-[...] genera reglas @supports y acepta cualquier cosa que usarías con @supports (...) entre corchetes, como un par propiedad/valor, e incluso expresiones que usen and y or.
Para abreviar, si solo necesitas verificar si una propiedad es compatible (y no un valor específico), simplemente puedes especificar el nombre de la propiedad:
<div class="bg-black/75 supports-backdrop-filter:bg-black/25 supports-backdrop-filter:backdrop-blur ..."> <!-- ... --></div>Usa la variante not-supports-[...] para estilizar elementos según si una determinada característica no es compatible con el navegador del usuario:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>Puedes configurar atajos para reglas @supports comunes que uses en tu proyecto creando una nueva variante en el espacio de nombres supports-*:
@custom-variant supports-grid { @supports (display: grid) { @slot; }}Luego puedes usar estas variantes personalizadas supports-* en tu proyecto:
<div class="supports-grid:grid"> <!-- ... --></div>Usa la variante starting para establecer la apariencia de un elemento cuando se renderiza por primera vez en el DOM, o cuando transiciona de display: none a visible:
<div> <button popovertarget="my-popover">Buscar actualizaciones</button> <div popover id="my-popover" class="opacity-0 starting:open:opacity-0 ..."> <!-- ... --> </div></div>Usa la variante aria-* para estilizar cosas condicionalmente según los atributos ARIA.
Por ejemplo, para aplicar la clase bg-sky-700 cuando el atributo aria-checked está configurado en true, usa la clase aria-checked:bg-sky-700:
<div aria-checked="true" class="bg-gray-600 aria-checked:bg-sky-700"> <!-- ... --></div>Por defecto, hemos incluido variantes para los atributos ARIA booleanos más comunes:
| Variante | CSS |
|---|---|
aria-busy | &[aria-busy="true"] |
aria-checked | &[aria-checked="true"] |
aria-disabled | &[aria-disabled="true"] |
aria-expanded | &[aria-expanded="true"] |
aria-hidden | &[aria-hidden="true"] |
aria-pressed | &[aria-pressed="true"] |
aria-readonly | &[aria-readonly="true"] |
aria-required | &[aria-required="true"] |
aria-selected | &[aria-selected="true"] |
Puedes personalizar qué variantes aria-* están disponibles creando una nueva variante:
@custom-variant aria-asc (&[aria-sort="ascending"]);@custom-variant aria-desc (&[aria-sort="descending"]);Si necesitas usar una variante aria única que no tiene sentido incluir en tu proyecto, o para atributos ARIA más complejos que toman valores específicos, usa corchetes para generar una propiedad sobre la marcha usando cualquier valor arbitrario:
| Número de factura # | Cliente | Monto |
|---|---|---|
| #100 | Pendant Publishing | $2,000.00 |
| #101 | Kruger Industrial Smoothing | $545.00 |
| #102 | J. Peterman | $10,000.25 |
<table> <thead> <tr> <th aria-sort="ascending" class="aria-[sort=ascending]:bg-[url('/img/down-arrow.svg')] aria-[sort=descending]:bg-[url('/img/up-arrow.svg')]" > Número de factura # </th> <!-- ... --> </tr> </thead> <!-- ... --></table>ARIA state variants can also target parent and sibling elements using the group-aria-* and peer-aria-* variants:
<table> <thead> <tr> <th aria-sort="ascending" class="group"> Número de factura # <svg class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"><!-- ... --></svg> </th> <!-- ... --> </tr> </thead> <!-- ... --></table>Usa la variante data-* para aplicar estilos condicionalmente según los atributos data.
Para verificar si existe un atributo data (y no un valor específico), simplemente puedes especificar el nombre del atributo:
<!-- Se aplicará --><div data-active class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div><!-- No se aplicará --><div class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div>Si necesitas verificar un valor específico, puedes usar un valor arbitrario:
<!-- Se aplicará --><div data-size="large" class="data-[size=large]:p-8"> <!-- ... --></div><!-- No se aplicará --><div data-size="medium" class="data-[size=large]:p-8"> <!-- ... --></div>Alternativamente, puedes configurar atajos para atributos data comunes que uses en tu proyecto creando una nueva variante en el espacio de nombres data-*:
@import "tailwindcss";@custom-variant data-checked (&[data-ui~="checked"]);Luego puedes usar estas variantes personalizadas data-* en tu proyecto:
<div data-ui="checked active" class="data-checked:underline"> <!-- ... --></div>Usa las variantes rtl y ltr para agregar estilos condicionalmente en modos de derecha a izquierda y de izquierda a derecha respectivamente cuando construyas diseños multidireccionales:
De izquierda a derecha
Tom Cook
Director de operaciones
De derecha a izquierda
تامر كرم
الرئيس التنفيذي
<div class="group flex items-center"> <img class="h-12 w-12 shrink-0 rounded-full" src="..." alt="" /> <div class="ltr:ml-3 rtl:mr-3"> <p class="text-gray-700 group-hover:text-gray-900 ...">...</p> <p class="text-gray-500 group-hover:text-gray-700 ...">...</p> </div></div>Recuerda que estas variantes solo son útiles si estás construyendo un sitio que necesite soportar diseños tanto de izquierda a derecha como de derecha a izquierda. Si estás construyendo un sitio que solo necesita soportar una única dirección, no necesitas estas variantes: simplemente aplica los estilos que tengan sentido para tu contenido.
Usa la variante open para agregar estilos condicionalmente cuando un elemento <details> o <dialog> esté en estado abierto:
Intenta alternar el desplegable para ver cómo cambian los estilos
La taza es redonda. El frasco es redondo. Deberían llamarlo Roundtine.
<details class="border border-transparent open:border-black/10 open:bg-gray-100 ..." open> <summary class="text-sm leading-6 font-semibold text-gray-900 select-none">¿Por qué lo llaman Ovaltine?</summary> <div class="mt-3 text-sm leading-6 text-gray-600"> <p>La taza es redonda. El frasco es redondo. Deberían llamarlo Roundtine.</p> </div></details>Esta variante también apunta a la pseudoclase :popover-open para popovers:
<div> <button popovertarget="my-popover">Open Popover</button> <div popover id="my-popover" class="opacity-0 open:opacity-100 ..."> <!-- ... --> </div></div>La variante inert te permite estilizar elementos marcados con el atributo inert:
<form> <legend>Preferencias de notificación</legend> <fieldset> <input type="radio" /> <label> Personalizado </label> <fieldset inert class="inert:opacity-50"> <!-- ... --> </fieldset> <input type="radio" /> <label> Todo </label> </fieldset></form>Esto es útil para agregar señales visuales que dejen claro que ciertas secciones de contenido no son interactivas.
Aunque por lo general es preferible colocar las clases de utilidad directamente en los elementos hijos, puedes usar la variante * en situaciones en las que necesites estilizar hijos directos sobre los cuales no tienes control:
<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>Es importante tener en cuenta que invalidar un estilo con una utilidad directamente en el propio hijo no funcionará, ya que las reglas de los hijos se generan después de las normales y tienen la misma especificidad:
No funcionará, los hijos no pueden invalidar los estilos que les ha dado el padre.
<ul class="*:bg-sky-50 ..."> <li class="bg-red-50 ...">Sales</li> <li>Marketing</li> <li>SEO</li> <!-- ... --></ul>Al igual que *, la variante ** se puede usar para estilizar los hijos de un elemento. La diferencia principal es que ** aplicará estilos a todos los descendientes, no solo a los hijos directos. Esto es especialmente útil cuando lo combinas con otra variante para limitar lo que estás seleccionando:
<ul class="**:data-avatar:size-12 **:data-avatar:rounded-full ..."> {#each items as item} <li> <img src={item.src} data-avatar /> <p>{item.name}</p> </li> {/each}</ul>Al igual que los valores arbitrarios te permiten usar valores personalizados con tus clases de utilidad, las variantes arbitrarias te permiten escribir variantes de selector personalizadas directamente en tu HTML.
Las variantes arbitrarias son solo cadenas de formato que representan el selector, envueltas entre corchetes. Por ejemplo, esta variante arbitraria cambia el cursor a grabbing cuando el elemento tiene la clase is-dragging:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:cursor-grabbing">{item}</li> {/each}</ul>Las variantes arbitrarias se pueden apilar con variantes integradas o entre sí, al igual que el resto de las variantes en Tailwind:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:active:cursor-grabbing">{item}</li> {/each}</ul>Si necesitas espacios en tu selector, puedes usar un guion bajo. Por ejemplo, esta variante arbitraria selecciona todos los elementos p dentro del elemento donde has agregado la clase:
<div class="[&_p]:mt-4"> <p>Lorem ipsum...</p> <ul> <li> <p>Lorem ipsum...</p> </li> <!-- ... --> </ul></div>También puedes usar at-rules como @media o @supports en variantes arbitrarias:
<div class="flex [@supports(display:grid)]:grid"> <!-- ... --></div>Con las variantes personalizadas de at-rule, el marcador de posición & no es necesario, al igual que al anidar con un preprocesador.
Si te encuentras usando la misma variante arbitraria varias veces en tu proyecto, podría valer la pena crear una variante personalizada usando la directiva @custom-variant:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));Ahora puedes usar la variante theme-midnight:<utility> en tu HTML:
<html data-theme="midnight"> <button class="theme-midnight:bg-black ..."></button></html>Obtén más información sobre cómo agregar variantes personalizadas en la documentación para agregar variantes personalizadas.
Una tabla de referencia rápida de cada una de las variantes incluidas en Tailwind por defecto.
| Variante | CSS |
|---|---|
| hover | @media (hover: hover) { &:hover } |
| focus | &:focus |
| focus-within | &:focus-within |
| focus-visible | &:focus-visible |
| active | &:active |
| visited | &:visited |
| target | &:target |
| * | :is(& > *) |
| ** | :is(& *) |
| has-[...] | &:has(...) |
| group-[...] | &:is(:where(.group)... *) |
| peer-[...] | &:is(:where(.peer)... ~ *) |
| in-[...] | :where(...) & |
| not-[...] | &:not(...) |
| inert | &:is([inert], [inert] *) |
| first | &:first-child |
| last | &:last-child |
| only | &:only-child |
| odd | &:nth-child(odd) |
| even | &:nth-child(even) |
| first-of-type | &:first-of-type |
| last-of-type | &:last-of-type |
| only-of-type | &:only-of-type |
| nth-[...] | &:nth-child(...) |
| nth-last-[...] | &:nth-last-child(...) |
| nth-of-type-[...] | &:nth-of-type(...) |
| nth-last-of-type-[...] | &:nth-last-of-type(...) |
| empty | &:empty |
| disabled | &:disabled |
| enabled | &:enabled |
| checked | &:checked |
| indeterminate | &:indeterminate |
| default | &:default |
| optional | &:optional |
| required | &:required |
| valid | &:valid |
| invalid | &:invalid |
| user-valid | &:user-valid |
| user-invalid | &:user-invalid |
| in-range | &:in-range |
| out-of-range | &:out-of-range |
| placeholder-shown | &:placeholder-shown |
| details-content | &:details-content |
| autofill | &:autofill |
| read-only | &:read-only |
| before | &::before |
| after | &::after |
| first-letter | &::first-letter |
| first-line | &::first-line |
| marker | &::marker, & *::marker |
| selection | &::selection |
| file | &::file-selector-button |
| backdrop | &::backdrop |
| placeholder | &::placeholder |
| sm | @media (width >= 40rem) |
| md | @media (width >= 48rem) |
| lg | @media (width >= 64rem) |
| xl | @media (width >= 80rem) |
| 2xl | @media (width >= 96rem) |
| min-[...] | @media (width >= ...) |
| max-sm | @media (width < 40rem) |
| max-md | @media (width < 48rem) |
| max-lg | @media (width < 64rem) |
| max-xl | @media (width < 80rem) |
| max-2xl | @media (width < 96rem) |
| max-[...] | @media (width < ...) |
| @3xs | @container (width >= 16rem) |
| @2xs | @container (width >= 18rem) |
| @xs | @container (width >= 20rem) |
| @sm | @container (width >= 24rem) |
| @md | @container (width >= 28rem) |
| @lg | @container (width >= 32rem) |
| @xl | @container (width >= 36rem) |
| @2xl | @container (width >= 42rem) |
| @3xl | @container (width >= 48rem) |
| @4xl | @container (width >= 56rem) |
| @5xl | @container (width >= 64rem) |
| @6xl | @container (width >= 72rem) |
| @7xl | @container (width >= 80rem) |
| @min-[...] | @container (width >= ...) |
| @max-3xs | @container (width < 16rem) |
| @max-2xs | @container (width < 18rem) |
| @max-xs | @container (width < 20rem) |
| @max-sm | @container (width < 24rem) |
| @max-md | @container (width < 28rem) |
| @max-lg | @container (width < 32rem) |
| @max-xl | @container (width < 36rem) |
| @max-2xl | @container (width < 42rem) |
| @max-3xl | @container (width < 48rem) |
| @max-4xl | @container (width < 56rem) |
| @max-5xl | @container (width < 64rem) |
| @max-6xl | @container (width < 72rem) |
| @max-7xl | @container (width < 80rem) |
| @max-[...] | @container (width < ...) |
| dark | @media (prefers-color-scheme: dark) |
| motion-safe | @media (prefers-reduced-motion: no-preference) |
| motion-reduce | @media (prefers-reduced-motion: reduce) |
| contrast-more | @media (prefers-contrast: more) |
| contrast-less | @media (prefers-contrast: less) |
| forced-colors | @media (forced-colors: active) |
| inverted-colors | @media (inverted-colors: inverted) |
| pointer-fine | @media (pointer: fine) |
| pointer-coarse | @media (pointer: coarse) |
| pointer-none | @media (pointer: none) |
| any-pointer-fine | @media (any-pointer: fine) |
| any-pointer-coarse | @media (any-pointer: coarse) |
| any-pointer-none | @media (any-pointer: none) |
| portrait | @media (orientation: portrait) |
| landscape | @media (orientation: landscape) |
| noscript | @media (scripting: none) |
@media print | |
| supports-[…] | @supports (…) |
| aria-busy | &[aria-busy="true"] |
| aria-checked | &[aria-checked="true"] |
| aria-disabled | &[aria-disabled="true"] |
| aria-expanded | &[aria-expanded="true"] |
| aria-hidden | &[aria-hidden="true"] |
| aria-pressed | &[aria-pressed="true"] |
| aria-readonly | &[aria-readonly="true"] |
| aria-required | &[aria-required="true"] |
| aria-selected | &[aria-selected="true"] |
| aria-[…] | &[aria-…] |
| data-[…] | &[data-…] |
| rtl | &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) |
| ltr | &:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *) |
| open | &:is([open], :popover-open, :open) |
| starting | @starting-style |
Esta es una lista completa de ejemplos para todas las variantes de pseudoclases incluidas en Tailwind para complementar la documentación de pseudoclases al comienzo de esta guía.
Estiliza un elemento cuando el usuario pasa el cursor del mouse sobre él usando la variante hover:
<div class="bg-black hover:bg-white ..."> <!-- ... --></div>Estiliza un elemento cuando tiene el foco usando la variante focus:
<input class="border-gray-300 focus:border-blue-400 ..." />Estiliza un elemento cuando este o uno de sus descendientes tiene el foco usando la variante focus-within:
<div class="focus-within:shadow-lg ..."> <input type="text" /></div>Estiliza un elemento cuando ha sido enfocado usando el teclado usando la variante focus-visible:
<button class="focus-visible:outline-2 ...">Submit</button>Estiliza un elemento cuando está siendo presionado usando la variante active:
<button class="bg-blue-500 active:bg-blue-600 ...">Submit</button>Estiliza un enlace cuando ya ha sido visitado usando la variante visited:
<a href="https://seinfeldquotes.com" class="text-blue-600 visited:text-purple-600 ..."> Inspiración </a>Estiliza un elemento si su ID coincide con el fragmento de URL actual usando la variante target:
<div id="about" class="target:shadow-lg ..."> <!-- ... --></div>Estiliza un elemento si es el primer hijo usando la variante first:
<ul> {#each people as person} <li class="py-4 first:pt-0 ..."> <!-- ... --> </li> {/each}</ul>Estiliza un elemento si es el último hijo usando la variante last:
<ul> {#each people as person} <li class="py-4 last:pb-0 ..."> <!-- ... --> </li> {/each}</ul>Estiliza un elemento si es el único hijo usando la variante only:
<ul> {#each people as person} <li class="py-4 only:py-0 ..."> <!-- ... --> </li> {/each}</ul>Estiliza un elemento si es un hijo con número impar usando la variante odd:
<table> {#each people as person} <tr class="bg-white odd:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>Estiliza un elemento si es un hijo con número par usando la variante even:
<table> {#each people as person} <tr class="bg-white even:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>Estiliza un elemento si es el primer hijo de su tipo usando la variante first-of-type:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="ml-2 first-of-type:ml-6 ..."> <!-- ... --> </a> {/each}</nav>Estiliza un elemento si es el último hijo de su tipo usando la variante last-of-type:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mr-2 last-of-type:mr-6 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento si es el único hijo de su tipo usando la variante only-of-type:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 only-of-type:mx-6 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento en una posición específica usando la variante nth:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-3:mx-6 nth-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento en una posición específica desde el final usando la variante nth-last:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-3:mx-6 nth-last-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento en una posición específica, del mismo tipo usando la variante nth-of-type:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-of-type-3:mx-6 nth-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento en una posición específica desde el final, del mismo tipo usando la variante nth-last-of-type:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-of-type-3:mx-6 nth-last-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>Más</button></nav>Estiliza un elemento si no tiene contenido usando la variante empty:
<ul> {#each people as person} <li class="empty:hidden ...">{person.hobby}</li> {/each}</ul>Estiliza un input cuando está deshabilitado usando la variante disabled:
<input class="disabled:opacity-75 ..." />Estiliza un input cuando está habilitado usando la variante enabled, lo cual es más útil cuando solo quieres aplicar otro estilo cuando un elemento no está deshabilitado:
<input class="enabled:hover:border-gray-400 disabled:opacity-75 ..." />Estiliza una casilla de verificación (checkbox) o botón de opción (radio button) cuando está seleccionado usando la variante checked:
<input type="checkbox" class="appearance-none checked:bg-blue-500 ..." />Estiliza una casilla de verificación (checkbox) o botón de opción (radio button) en estado indeterminado usando la variante indeterminate:
<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />Estiliza una opción, casilla de verificación (checkbox) o botón de opción (radio button) que era el valor por defecto cuando la página se cargó inicialmente usando la variante default:
<input type="checkbox" class="default:outline-2 ..." />Estiliza un input cuando es opcional usando la variante optional:
<input class="border optional:border-red-500 ..." />Estiliza un input cuando es obligatorio usando la variante required:
<input required class="border required:border-red-500 ..." />Estiliza un input cuando es válido usando la variante valid:
<input required class="border valid:border-green-500 ..." />Estiliza un input cuando es inválido usando la variante invalid:
<input required class="border invalid:border-red-500 ..." />Estiliza un input cuando es válido y el usuario ha interactuado con él, usando la variante user-valid:
<input required class="border user-valid:border-green-500" />Estiliza un input cuando es inválido y el usuario ha interactuado con él, usando la variante user-invalid:
<input required class="border user-invalid:border-red-500" />Estiliza un input cuando su valor está dentro del límite de rango especificado usando la variante in-range:
<input min="1" max="5" class="in-range:border-green-500 ..." />Estiliza un input cuando su valor está fuera del límite de rango especificado usando la variante out-of-range:
<input min="1" max="5" class="out-of-range:border-red-500 ..." />Estiliza un input cuando se muestra el marcador de posición (placeholder) usando la variante placeholder-shown:
<input class="placeholder-shown:border-gray-500 ..." placeholder="you@example.com" />Estiliza el contenido de un elemento <details> usando la variante details-content:
<details class="details-content:bg-gray-100 ..."> <summary>Details</summary> Esto es un secreto.</details>Estiliza un input cuando el navegador lo ha completado automáticamente usando la variante autofill:
<input class="autofill:bg-yellow-200 ..." />Estiliza un input cuando es de solo lectura usando la variante read-only:
<input class="read-only:bg-gray-100 ..." />