Cheatsheet Tailwind CSS
Framework CSS utility-first
Tailwind CSS
Instalação e Configuração
Instalación (Vite + v4)
npm install -D tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
export default {
plugins: [tailwindcss()]
}
/* input.css */
@import "tailwindcss";
/* Build: npm run dev / npm run build */En Tailwind v4, instala @tailwindcss/vite y añádelo al array plugins. El CSS usa solo @import "tailwindcss" (reemplaza las 3 directivas @tailwind base/components/utilities de v3). Vite procesa todo automáticamente sin necesidad de postcss.config.js ni tailwind.config.js.
Escala de espaciado
/* 1 unidad = 0.25rem (4px) */ p-1 = 0.25rem (4px) p-2 = 0.5rem (8px) p-4 = 1rem (16px) p-8 = 2rem (32px) p-16 = 4rem (64px) /* Valores disponibles: */ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96 /* Misma escala para: p, m, w, h, gap, size, space */
La escala es consistente en todo el framework: cada unidad = 0.25rem (4px). p-4 = 16px, m-8 = 32px, w-16 = 64px. La misma escala se aplica a padding, margin, width, height, gap, size y space. Los valores mayores (72, 80, 96) son para layouts y secciones. Usa [valor] para valores arbitrarios fuera de la escala.
Plugins oficiales
// tailwind.config.js (v3)
module.exports = {
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
require('@tailwindcss/container-queries'),
]
}
/* v4: importar en el CSS */
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";Los plugins oficiales extienden Tailwind: @tailwindcss/forms estiliza inputs con un reset consistente. typography añade la clase prose para contenido HTML rico (markdown, CMS). aspect-ratio para proporciones (vídeos). container-queries para estilos basados en el contenedor. En v4, usa @plugin en el CSS en vez de require().
Laravel + Blade + Vite
/* 1. Instalar */
npm install -D tailwindcss @tailwindcss/vite
/* 2. resources/css/app.css */
@import "tailwindcss";
/* 3. vite.config.js */
import tailwindcss from '@tailwindcss/vite'
export default {
plugins: [laravel({ input: ['resources/css/app.css',
'resources/js/app.js'], refresh: true }),
tailwindcss()]
}
/* 4. Blade: */
@vite(['resources/css/app.css', 'resources/js/app.js'])Integración con Laravel: instala Tailwind + el plugin de Vite, impórtalo en app.css, configura vite.config.js con los plugins laravel() y tailwindcss(). En Blade, usa la directiva @vite para cargar los assets. Con refresh: true, los cambios en los ficheros Blade recargan el navegador automáticamente.
Instalación (PostCSS / v3)
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
// tailwind.config.js
module.exports = {
content: ["./src/**/*.{html,js,vue,blade.php}"],
theme: { extend: {} },
plugins: [],
}
/* input.css */
@tailwind base;
@tailwind components;
@tailwind utilities;En v3, usa postcss + autoprefixer. El campo content define los ficheros que Tailwind analiza para generar solo el CSS usado (tree-shaking). Las 3 directivas @tailwind importan las capas: base (reset/preflight), components y utilities. El init -p crea también el postcss.config.js.
Personalizar tema (v3 config)
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
marca: '#1fb6ff',
'marca-dark': '#009eeb',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Clash Display', 'sans-serif'],
},
spacing: { '128': '32rem' },
borderRadius: { '4xl': '2rem' },
}
}
}theme.extend añade valores sin reemplazar los predeterminados de Tailwind. colors crea colores custom utilizables como bg-marca, text-marca. fontFamily define fuentes (font-sans, font-display). spacing añade valores a la escala (p-128). Sin extend, reemplaza TODO — usa siempre extend para no perder los predeterminados.
Prettier (orden de clases)
npm install -D prettier prettier-plugin-tailwindcss
// .prettierrc
{
"plugins": ["prettier-plugin-tailwindcss"]
}
/* Antes (desordenado): */
class="text-white p-4 bg-blue-500 rounded flex mt-2"
/* Después (ordenado automáticamente): */
class="mt-2 flex rounded bg-blue-500 p-4 text-white"El plugin prettier-plugin-tailwindcss ordena las clases automáticamente en el orden canónico de Tailwind (layout → flex → grid → spacing → sizing → typography → colors → effects). Elimina inconsistencias en el equipo y facilita la lectura. Funciona con HTML, Vue, React, Blade, Astro. Muy recomendado en cualquier proyecto.
content (tree-shaking)
// tailwind.config.js (v3)
module.exports = {
content: [
"./index.html",
"./src/**/*.{html,js,ts,vue,jsx,tsx}",
"./resources/views/**/*.blade.php",
"./app/Livewire/**/*.php",
],
}
/* v4: detección automática (sin config) */
/* Usa @source para añadir rutas extra: */
@source "../vendor/laravel/framework/src";content le dice a Tailwind qué ficheros analizar para extraer las clases usadas. Solo se genera el CSS de las clases encontradas (tree-shaking). Incluye TODOS los ficheros con clases: HTML, JS, Vue, Blade, PHP (Livewire). En v4, la detección es automática en la mayoría de los casos. Usa @source para rutas fuera del proyecto (ej.: vendor). Si una clase no aparece, probablemente falta el fichero en content.
Vía CDN (Play CDN)
<!-- Solo para prototipos y desarrollo -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Configuración inline (opcional): -->
<script>
tailwind.config = {
theme: {
extend: {
colors: { marca: '#1fb6ff' }
}
}
}
</script>
<!-- Uso inmediato: -->
<div class="p-4 bg-marca text-white">Hola!</div>El Play CDN es solo para prototipos y aprendizaje — no lo uses en producción (genera CSS en runtime, sin tree-shaking). Permite probar clases inmediatamente sin build. La configuración se hace vía el objeto tailwind.config inline. Para producción, usa siempre Vite o PostCSS.
Personalizar tema (v4 CSS)
/* input.css — Tailwind v4 */
@import "tailwindcss";
@theme {
--color-marca: #1fb6ff;
--color-marca-dark: #009eeb;
--font-sans: 'Inter', sans-serif;
--font-display: 'Clash Display', sans-serif;
--spacing-128: 32rem;
--breakpoint-3xl: 1920px;
--radius-4xl: 2rem;
}
/* Uso: bg-marca, font-display, p-128, 3xl:flex, rounded-4xl */En v4, la configuración se hace en CSS con @theme — no necesitas tailwind.config.js. Define variables --color-*, --font-*, --spacing-*, --breakpoint-*. Cada variable genera utilidades automáticamente: --color-marca → bg-marca, text-marca, border-marca. Más simple y con autocompletado en el editor.
CLI y build
/* Build para producción (v3 CLI standalone) */ npx tailwindcss -i input.css -o output.css --minify /* Watch en desarrollo */ npx tailwindcss -i input.css -o output.css --watch /* v4 con Vite (no necesita CLI separado) */ npm run dev /* vite dev — hot reload */ npm run build /* vite build — CSS optimizado */ /* El output final es minúsculo (tree-shaking) */ /* Proyecto grande: ~10-30kb de CSS final */
El CLI compila el CSS: -i (input), -o (output), --minify (producción), --watch (desarrollo con hot reload). En v4 con Vite, el build está integrado (vite build). El output final es minúsculo porque el tree-shaking elimina todas las clases no usadas en el HTML. Un proyecto grande genera típicamente 10-30kb de CSS.
Uso básico (utility-first)
<div class="p-4 bg-blue-500 text-white rounded-lg shadow-md"> Hola Tailwind! </div> <button class="px-6 py-2 bg-green-600 text-white font-semibold rounded-full hover:bg-green-700 transition duration-200"> Clica aqui </button> <a href="#" class="text-blue-600 underline hover:text-blue-800">Link</a>
El concepto utility-first: compón el diseño con clases pequeñas directamente en el HTML, sin escribir CSS custom. p-4 = padding de 1rem, bg-blue-500 = fondo azul, rounded-lg = esquinas redondeadas, shadow-md = sombra media. Cada clase hace UNA cosa. El resultado es un diseño consistente y sin ficheros CSS separados.
Valores arbitrarios
/* Cualquier valor con [ ] */
w-[300px]
h-[calc(100vh-64px)]
bg-[#1fb6ff]
text-[13px]
grid-cols-[1fr_2fr_1fr]
top-[117px]
shadow-[0_0_10px_rgba(0,0,0,0.3)]
tracking-[0.2em]
max-w-[1400px]
z-[999]
/* Underscores = espacios */
bg-[url('/img/hero.png')]Los corchetes [ ] permiten cualquier valor CSS sin configurar el tema. w-[300px] = width exacto de 300px. bg-[#1fb6ff] = color hexadecimal custom. grid-cols-[1fr_2fr] = template custom. Usa underscores en vez de espacios dentro de los corchetes. Ideal para valores únicos que no justifican una entrada en el tema.
Preflight (reset CSS)
/* Tailwind aplica un reset global (preflight): */
- margin: 0 en todos los elementos
- box-sizing: border-box globalmente
- border: 0 solid (sin borde por defecto)
- img, svg, video: display block, max-width 100%
- button, input: font inherit, sin estilos
- h1-h6, p: font-size/weight heredados
- a: color inherit, text-decoration inherit
- ul, ol: list-style none, padding 0
/* Desactivar (no recomendado): */
corePlugins: { preflight: false }El preflight es el reset CSS de Tailwind (basado en modern-normalize). Elimina los márgenes, paddings y estilos por defecto del navegador. Define box-sizing: border-box globalmente. Las imágenes pasan a display: block con max-width: 100%. Los botones e inputs heredan la fuente. Por eso necesitas añadir border explícitamente para ver bordes.
Layout e Display
Display
block /* display: block */ inline-block /* display: inline-block */ inline /* display: inline */ flex /* display: flex */ inline-flex /* display: inline-flex */ grid /* display: grid */ inline-grid /* display: inline-grid */ hidden /* display: none */ contents /* display: contents */ table /* display: table */ /* Responsivo: */ class="hidden md:flex" /* oculto en mobile, flex en md+ */ class="block lg:hidden" /* visible solo en mobile */
block, inline, flex, grid controlan el tipo de visualización del elemento. hidden lo elimina completamente del flujo (como display: none). contents hace que el elemento "desaparezca" manteniendo los hijos visibles en el layout. Combina con breakpoints para mostrar/ocultar responsivamente: hidden md:flex es el patrón más usado.
Z-index
z-0, z-10, z-20, z-30, z-40, z-50 z-auto /* z-index: auto */ -z-10 /* negativo (detrás) */ z-[100] /* arbitrario */ /* Convención sugerida: */ /* Contenido base: z-0 (o sin z-index) */ /* Dropdown/menu: z-10 */ /* Sticky header: z-20 */ /* Sidebar: z-30 */ /* Modal overlay: z-40 */ /* Modal/toast: z-50 */ /* Requiere position: relative/absolute/fixed/sticky */
z-0 a z-50 controlan el orden de apilamiento (qué elemento queda por encima). z-auto = sin z-index. Usa z-[100] para valores custom. Adopta una convención en el equipo: contenido z-0, dropdowns z-10, sticky z-20, modales z-50. Solo funciona con position (relative, absolute, fixed o sticky).
Float y clear
float-start /* izquierda en LTR, derecha en RTL */ float-end /* derecha en LTR, izquierda en RTL */ float-none /* sin float */ clear-both /* limpia floats */ clearfix /* pseudo-elemento ::after en el padre */ /* Uso legacy (texto alrededor de una imagen): */ <img class="float-start me-4 mb-2 w-32" src="foto.jpg"> <p>Texto flui à volta da imagen...</p> /* HOY: prefiere flex o grid para layouts */
float-* es legacy — hoy prefiere flex o grid para layouts. float-start/float-end son RTL-aware (reemplazan float-left/float-right). clearfix limpia los floats en el padre (evita el colapso de altura). Se mantiene por compatibilidad con layouts antiguos y para el caso de uso de texto fluyendo alrededor de una imagen.
Box sizing
box-border /* width incluye padding + border (default TW) */ box-content /* width solo del contenido */ /* Tailwind aplica box-border globalmente vía preflight */ /* Ejemplo con box-content: */ <div class="box-content w-32 p-4 border-2"> /* Contenido: 128px */ /* Total renderizado: 128 + 32 (padding) + 4 (border) = 164px */ </div> /* Con box-border (por defecto): */ <div class="box-border w-32 p-4 border-2"> /* Total: 128px (el contenido encoge para caber) */ </div>
Tailwind aplica box-sizing: border-box globalmente vía preflight. box-border = la width incluye padding y border (más intuitivo). box-content = la width es solo del contenido (comportamiento CSS original). Rara vez necesitas cambiarlo — border-box es más predecible porque w-32 es siempre 128px independientemente del padding.
Container
<div class="container mx-auto px-4">
Contenido centrado com padding lateral
</div>
/* Config (v3): */
container: {
center: true,
padding: { DEFAULT: '1rem', sm: '2rem' },
screens: { '2xl': '1400px' }
}
/* v4 (CSS): */
@utility container {
margin-inline: auto;
padding-inline: 1rem;
}container define un ancho máximo responsivo que cambia en cada breakpoint (640px, 768px, 1024px, 1280px, 1536px). mx-auto lo centra horizontalmente. px-4 añade padding lateral para que no se pegue a los bordes. En v3, configura center: true para centrar automáticamente. En v4, usa @utility para personalizarlo.
Overflow
overflow-auto /* scroll si es necesario */ overflow-hidden /* corta lo que sobra */ overflow-visible /* muestra (por defecto) */ overflow-scroll /* siempre scroll */ overflow-x-auto /* scroll horizontal */ overflow-y-hidden /* corta vertical */ overflow-clip /* corta sin crear scroll container */ /* Truncar texto (1 línea): */ class="truncate" /* = overflow-hidden + text-ellipsis + whitespace-nowrap */ /* Tabla ancha en mobile: */ <div class="overflow-x-auto"> <table class="w-full">...</table> </div>
overflow-hidden corta el contenido que sobra — esencial con rounded-* para que las imágenes no sobrepasen las esquinas. overflow-x-auto para tablas anchas en mobile (scroll horizontal). truncate = atajo para texto de una línea con puntos suspensivos. overflow-clip corta sin crear scroll container (más performante). overflow-auto muestra scroll solo cuando es necesario.
Visibility y object-fit
visible /* visibility: visible */ invisible /* visibility: hidden (ocupa espacio) */ collapse /* visibility: collapse (tablas) */ /* Object-fit (imágenes/vídeos): */ object-contain /* cabe todo (puede tener barras) */ object-cover /* rellena recortando */ object-fill /* estira (distorsiona) */ object-none /* tamaño original */ object-scale-down /* el menor entre none y contain */ /* Thumbnail uniforme en grid: */ <img class="w-full h-48 object-cover" src="foto.jpg">
invisible oculta pero mantiene el espacio ocupado (a diferencia de hidden que lo quita del flujo). object-cover rellena el contenedor recortando lo que sobra (thumbnails, hero images). object-contain muestra la imagen entera (puede tener barras). Combina con w-full h-48 para imágenes de tamaño uniforme en grids. object-fill distorsiona — evítalo.
Layout clásico (sidebar + main)
/* Flexbox: */ <div class="flex min-h-screen"> <aside class="w-64 shrink-0 bg-gray-100 p-4">Sidebar</aside> <main class="flex-1 p-8">Contenido</main> </div> /* Grid: */ <div class="grid grid-cols-1 md:grid-cols-[250px_1fr] min-h-screen"> <aside class="bg-gray-100 p-4">Sidebar</aside> <main class="p-8">Contenido</main> </div> /* Responsivo: la sidebar desaparece en mobile */ <aside class="hidden md:block w-64">Sidebar</aside>
Dos patrones para sidebar + contenido: flex con w-64 shrink-0 (sidebar fija) + flex-1 (main se estira), o grid con grid-cols-[250px_1fr] (template explícito). min-h-screen garantiza una altura mínima de pantalla completa. Responsivo: hidden md:block oculta la sidebar en mobile. Grid es más explícito; flex es más flexible.
Position
static /* por defecto (sin posicionamiento) */ relative /* relativo a su posición normal */ absolute /* relativo al padre relative más cercano */ fixed /* relativo al viewport (siempre visible) */ sticky /* se pega al scroll cuando alcanza el offset */ /* Patrón clásico: padre relative + hijo absolute */ <div class="relative"> <div class="absolute top-0 right-0">Badge</div> </div> /* Navbar fija al scroll: */ <nav class="sticky top-0 z-50">Menu</nav>
relative en el padre + absolute en el hijo es el patrón de posicionamiento. sticky top-0 se pega arriba al hacer scroll (navbar, headers de tabla). fixed = siempre visible en el viewport (toasts, FAB, modales). static es el valor por defecto (sin posicionamiento). Coordenadas: top-0, right-0, inset-0 (todos los lados). Combina siempre con z-index para controlar las capas.
Aspect ratio
aspect-auto /* proporción natural */ aspect-square /* 1/1 (cuadrado) */ aspect-video /* 16/9 (vídeo) */ aspect-[4/3] /* arbitrario */ aspect-[21/9] /* ultrawide */ /* Vídeo responsivo: */ <div class="aspect-video w-full"> <iframe class="w-full h-full" src="..."></iframe> </div> /* Avatar cuadrado: */ <img class="aspect-square w-24 object-cover rounded-full">
aspect-video = proporción 16:9 para vídeos responsivos (YouTube, Vimeo). aspect-square = 1:1 para avatares y thumbnails. aspect-[4/3] para ratios custom. Reemplaza el viejo hack de padding-bottom porcentual. El contenido se estira automáticamente para rellenar la proporción definida. Combina con object-cover para imágenes.
Pointer events y user select
pointer-events-none /* no clica (overlay, loading) */ pointer-events-auto /* restaura los clics */ select-none /* texto no seleccionable */ select-text /* seleccionable (por defecto) */ select-all /* selecciona todo al clicar */ select-auto /* Overlay de loading (no bloquea los clics): */ <div class="absolute inset-0 bg-white/50 pointer-events-none flex items-center justify-center"> <span class="animate-spin text-2xl">⟳</span> </div> /* Botón con icono (el icono no interfiere): */ <button><svg class="pointer-events-none">...</svg> Texto</button>
pointer-events-none desactiva los clics en el elemento (overlays decorativos, iconos dentro de botones, loading spinners). select-none impide la selección de texto (botones, labels, UI). select-all selecciona todo al clicar (códigos, URLs, claves API). Combina con pointer-events-auto en un hijo para reactivar los clics en elementos específicos dentro de un padre desactivado.
Coordenadas (inset)
top-0, top-1/2, top-full, -top-4 bottom-0, left-0, right-0 inset-0 /* top+right+bottom+left: 0 */ inset-x-0 /* left + right: 0 */ inset-y-0 /* top + bottom: 0 */ start-0 /* left en LTR, right en RTL */ end-0 /* right en LTR, left en RTL */ /* Centrar con absolute (patrón): */ class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" /* Overlay full-screen: */ class="absolute inset-0 bg-black/50"
inset-0 = todos los lados a 0 (overlay full-screen, backgrounds). inset-x-0 = solo horizontal. start/end son propiedades lógicas (RTL-aware). Para centrar un elemento: absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2. Valores negativos con prefijo - (ej.: -top-4 para superponer).
Columns (multi-columna)
columns-1, columns-2, columns-3, columns-4 columns-auto columns-[250px] /* ancho mínimo por columna */ <div class="columns-2 md:columns-3 gap-8"> <p class="break-inside-avoid mb-4">Texto...</p> <p class="break-inside-avoid mb-4">Texto...</p> <img class="break-inside-avoid mb-4" src="foto.jpg"> </div> /* break-inside-avoid impide la ruptura en medio del elemento */
columns-* crea un layout multi-columna (como periódico/revista). columns-2 md:columns-3 = 2 columnas en mobile, 3 en md+. gap-8 espacia las columnas. break-inside-avoid impide que un elemento se parta entre columnas. Ideal para listas de links, FAQs, galerías masonry y contenido editorial. El contenido fluye de arriba abajo en cada columna.
Isolation y contain
isolate /* isolation: isolate (nuevo stacking context) */ isolation-auto contain-none contain-layout /* aísla el layout */ contain-paint /* aísla el paint (clip) */ contain-size /* aísla el tamaño */ contain-strict /* layout + paint + size */ contain-content /* layout + paint */ /* Problema: un hijo con -z-10 queda detrás del padre */ /* Solución: isolate en el padre */ <div class="isolate relative bg-white"> <div class="absolute -z-10">Fondo decorativo</div> </div>
isolate crea un nuevo stacking context — impide que los hijos con z-index negativo queden detrás del padre (un problema común con backgrounds decorativos). contain-* optimiza el rendimiento aislando layout/paint del resto de la página. contain-paint impide que los hijos se "escapen" visualmente. Útil para componentes complejos, animaciones y listas largas.
Espaçamento e Dimensões
Padding
p-4 /* todos los lados (1rem = 16px) */ px-4 /* izquierda + derecha (horizontal) */ py-2 /* arriba + abajo (vertical) */ pt-4 /* solo arriba */ pr-2 /* solo derecha */ pb-4 /* solo abajo */ pl-2 /* solo izquierda */ ps-4 /* start (LTR: izquierda, RTL: derecha) */ pe-4 /* end (LTR: derecha, RTL: izquierda) */ /* Responsivo: */ class="p-4 md:p-8" /* más padding en desktop */
p = padding. Sufijos: x (horizontal), y (vertical), t/b/l/r (lados físicos), s/e (lados lógicos, RTL-aware). Escala: 0 a 96 (cada unidad = 0.25rem). p-4 = 16px. Acepta prefijos responsivos: p-4 md:p-8 = más padding en desktop.
Size (v3.4+)
size-4 /* width + height: 1rem (16px) */ size-8 /* 2rem x 2rem (32px) */ size-12 /* 3rem x 3rem (48px) */ size-full /* 100% x 100% */ size-screen /* 100vw x 100vh */ size-fit /* fit-content ambos */ size-auto /* Iconos: */ <svg class="size-5 text-gray-500">...</svg> /* Avatar: */ <img class="size-12 rounded-full object-cover" src="avatar.jpg"> /* Thumbnail cuadrado: */ <img class="size-24 rounded-lg object-cover" src="foto.jpg">
size-* define width Y height simultáneamente (atajo para w-* h-*). size-12 = 48px × 48px. Perfecto para iconos (size-5 = 20px), avatares (size-12 rounded-full) y thumbnails cuadrados (size-24). Elimina la repetición w-* h-*. Disponible desde Tailwind v3.4. Acepta responsivo: size-12 md:size-16.
Padding responsivo
/* Secciones con padding progresivo: */ class="py-8 md:py-16 lg:py-24" /* Container con padding lateral adaptativo: */ class="px-4 sm:px-6 lg:px-8" /* Card con padding responsivo: */ class="p-4 md:p-6 lg:p-8" /* Hero con más espacio: */ <section class="py-16 md:py-24 lg:py-32"> <div class="px-4 md:px-0">Contenido</div> </section> /* Regla: más espacio en pantallas más grandes */
El padding responsivo es esencial para diseños profesionales: py-8 md:py-16 lg:py-24 = secciones con más espacio vertical en pantallas más grandes. px-4 sm:px-6 lg:px-8 = padding lateral progresivo. Regla general: mobile tiene menos espacio (pantalla pequeña), desktop tiene más (más espacio disponible). Evita diseños "apretados" en desktop o "anchos" en mobile.
Margin
m-4 /* todos los lados */ mx-auto /* centra horizontalmente */ my-4 /* arriba + abajo */ mt-4 /* arriba */ mb-0 /* elimina el margen inferior */ ms-2 /* start (RTL-aware) */ -me-2 /* end negativo */ -mt-4 /* margin-top negativo (tira hacia arriba) */ /* Centrar bloque de ancho fijo: */ <div class="max-w-4xl mx-auto px-4">Contenido</div> /* Superposición (el card sube sobre la sección anterior): */ <div class="-mt-8 relative z-10">Card</div>
m = margin, misma lógica que el padding. mx-auto centra bloques de ancho fijo (esencial con max-w-*). Valores negativos con prefijo -: -mt-4 (tira hacia arriba), -me-2. Útil para superposiciones y ajustes finos. mb-0 elimina el margen inferior. ms/me son RTL-aware.
max-width (content)
max-w-xs /* 20rem (320px) */ max-w-sm /* 24rem (384px) */ max-w-md /* 28rem (448px) */ max-w-lg /* 32rem (512px) */ max-w-xl /* 36rem (576px) */ max-w-2xl /* 42rem (672px) */ max-w-4xl /* 56rem (896px) */ max-w-7xl /* 80rem (1280px) */ max-w-prose /* 65ch (ancho ideal de lectura) */ max-w-screen-xl /* 1280px (breakpoint xl) */ /* Artículo legible: */ <article class="max-w-prose mx-auto">Texto largo...</article> /* Container de página: */ <div class="max-w-7xl mx-auto px-4">...</div>
max-w-* limita el ancho máximo. max-w-prose = 65 caracteres (ancho ideal de lectura para texto largo). max-w-7xl = 80rem (container de página). max-w-screen-xl = el ancho del breakpoint xl. Combina con mx-auto para centrar. Esencial para la legibilidad — el texto al 100% de ancho es difícil de leer.
min-w-0 y overflow en flex
/* PROBLEMA: el texto no se trunca en flex */
<div class="flex">
<img class="size-12" src="avatar.jpg">
<p class="truncate">Texto muy largo...</p>
<!-- truncate NO funciona sin min-w-0! -->
</div>
/* SOLUCIÓN: min-w-0 en el hijo flexible */
<div class="flex gap-4">
<img class="shrink-0 size-12" src="avatar.jpg">
<div class="min-w-0">
<p class="truncate">Texto muy largo que ahora trunca correctamente...</p>
</div>
</div>min-w-0 es ESENCIAL en flex/grid para permitir que el contenido encoja por debajo de su tamaño natural. Sin él, truncate y overflow-hidden no funcionan porque el elemento flex tiene min-width: auto por defecto (no encoge por debajo del contenido). Añade min-w-0 al hijo que necesita truncar + shrink-0 en los elementos fijos.
Width
w-full /* 100% */ w-screen /* 100vw */ w-auto /* automática */ w-1/2 /* 50% */ w-1/3 /* 33.33% */ w-2/3 /* 66.67% */ w-1/4 /* 25% */ w-3/4 /* 75% */ w-64 /* 16rem (256px) */ w-fit /* fit-content */ w-min /* min-content */ w-max /* max-content */ /* Responsivo: */ class="w-full md:w-1/2 lg:w-1/3"
w-full = 100% del padre. Fracciones: w-1/2 (50%), w-2/3 (66%), w-3/4 (75%). w-fit = se ajusta al contenido. w-screen = 100% del viewport. Responsivo: w-full md:w-1/2 lg:w-1/3 = ancho total en mobile, la mitad en tablet, un tercio en desktop. Combina con max-w-* para limitarlo.
space-between (espacio entre hijos)
/* Añade margen entre los hijos (excepto el 1º) */ space-x-4 /* margin-left: 1rem en los hijos */ space-y-2 /* margin-top: 0.5rem en los hijos */ space-x-reverse space-y-reverse /* Stack vertical (formularios, listas): */ <div class="space-y-4"> <p>Párrafo 1</p> <p>Párrafo 2</p> <p>Párrafo 3</p> </div> /* HOY: prefiere flex/grid + gap */ <div class="flex flex-col gap-4"> ← moderno
space-y-* añade margen vertical entre los hijos (sin tocar el primero). Útil para listas de párrafos, stacks de botones, formularios. Hoy, flex flex-col gap-4 es preferible (más simple, sin selectores > * + *). space-x-reverse invierte la dirección (para RTL o flex-row-reverse). Se mantiene por compatibilidad.
Dimensiones responsivas
/* Ancho adaptativo: */ class="w-full md:w-1/2 lg:w-1/3" /* Altura adaptativa: */ class="h-48 md:h-64 lg:h-96" /* Size adaptativo: */ class="size-12 md:size-16" /* Max-width por breakpoint: */ class="max-w-sm md:max-w-md lg:max-w-2xl" /* Imagen responsiva: */ <img class="w-full h-auto md:w-1/2 md:h-64 object-cover"> /* Regla: define mobile-first y sobrescribe */
Las dimensiones responsivas siguen el patrón mobile-first: define el valor base (mobile) y sobrescribe en breakpoints mayores. w-full md:w-1/2 = 100% en mobile, 50% en md+. h-48 md:h-64 = más altura en desktop. size-12 md:size-16 = iconos/avatares más grandes. Combina siempre con object-cover para que las imágenes no se distorsionen.
Height
h-full /* 100% del padre */ h-screen /* 100vh (viewport) */ h-auto /* automática */ h-16 /* 4rem (64px) */ h-1/2 /* 50% del padre */ max-h-96 /* max-height: 24rem */ min-h-screen /* min-height: 100vh */ min-h-0 /* min-height: 0 */ /* Hero section full-height: */ <section class="min-h-screen flex items-center">...</section> /* Modal con scroll: */ <div class="max-h-[80vh] overflow-y-auto">...</div>
h-screen = 100% del viewport. min-h-screen = altura mínima de pantalla completa (hero sections, páginas de login — el contenido puede crecer). max-h-* limita la altura máxima (modales, dropdowns con scroll). h-full requiere que el padre tenga una altura definida. min-h-0 es necesario en flex/grid para permitir overflow.
Margin negativo
/* Prefijo - para valores negativos */ -mt-4 /* margin-top: -1rem (tira hacia arriba) */ -ml-2 /* margin-left: -0.5rem */ -mx-4 /* margen negativo horizontal */ -inset-2 /* top/right/bottom/left: -0.5rem */ /* Card que se superpone a la sección anterior: */ <section class="bg-blue-600 pb-16">Hero</section> <div class="-mt-8 mx-auto max-w-4xl bg-white rounded-xl shadow-lg p-8"> Card sobreposto </div> /* Imagen que "sale" del contenedor: */ <img class="-mx-4 w-[calc(100%+2rem)]" src="wide.jpg">
Valores negativos con prefijo -: -mt-4 tira del elemento hacia arriba (superposición). Patrón clásico: hero con pb-16 + card con -mt-8 (el card sube sobre el hero). -mx-4 para imágenes que "salen" del padding del contenedor. -inset-2 para overlays ligeramente más grandes. Esencial para diseños con superposiciones y profundidad.
Box sizing y contain
box-border /* width incluye padding + border (default TW) */ box-content /* width solo del contenido */ /* contain (performance): */ contain-none contain-layout /* aísla el layout */ contain-paint /* aísla el paint (clip visual) */ contain-size /* aísla el tamaño */ contain-strict /* layout + paint + size */ contain-content /* layout + paint */ /* Optimizar listas largas: */ <div class="contain-content"> <!-- 1000 items --> </div>
Tailwind aplica box-sizing: border-box globalmente vía preflight — la width incluye padding y border. box-content revierte al comportamiento original (width solo del contenido). contain-* optimiza el rendimiento: contain-paint impide que los hijos se "escapen" visualmente, contain-layout aísla el layout. Útil para listas largas y componentes independientes.
Tipografia
Tamaño de fuente
text-xs /* 0.75rem (12px) + line-height 1rem */ text-sm /* 0.875rem (14px) + line-height 1.25rem */ text-base /* 1rem (16px) — por defecto del navegador */ text-lg /* 1.125rem (18px) */ text-xl /* 1.25rem (20px) */ text-2xl /* 1.5rem (24px) */ text-3xl /* 1.875rem (30px) */ text-4xl /* 2.25rem (36px) */ text-5xl /* 3rem (48px) */ text-6xl ... text-9xl /* Responsivo: */ class="text-xl md:text-3xl lg:text-5xl"
text-* define el tamaño de la fuente Y el line-height proporcional automáticamente. text-base = 16px (por defecto del navegador). text-sm/text-xs para texto secundario. text-4xl a text-9xl para títulos hero. Responsivo: text-xl md:text-3xl lg:text-5xl = menor en mobile, mayor en desktop.
Line height y letter spacing
/* Line height (interlineado): */ leading-none /* 1 (sin espacio) */ leading-tight /* 1.25 (títulos) */ leading-snug /* 1.375 */ leading-normal /* 1.5 (por defecto) */ leading-relaxed /* 1.625 (cuerpo de texto) */ leading-loose /* 2 (mucho espacio) */ /* Letter spacing (tracking): */ tracking-tighter /* -0.05em */ tracking-tight /* -0.025em (títulos grandes) */ tracking-normal /* 0 */ tracking-wide /* 0.025em (mayúsculas) */ tracking-wider /* 0.05em */ tracking-widest /* 0.1em */
leading-* controla el interlineado (espacio entre líneas). leading-tight para títulos (líneas próximas), leading-relaxed para el cuerpo de texto (más espacio, más legible). tracking-* controla el espaciado entre letras. tracking-wide para texto en mayúsculas, tracking-tight para títulos grandes (letras más juntas).
Text overflow y wrapping
text-ellipsis /* puntos suspensivos (con truncate) */ text-clip /* corta sin puntos suspensivos */ whitespace-normal /* corte normal (por defecto) */ whitespace-nowrap /* nunca corta */ whitespace-pre /* preserva espacios y \n */ whitespace-pre-wrap /* preserva + permite corte */ whitespace-break-spaces /* como pre-wrap + corta espacios */ /* Código con scroll horizontal: */ <pre class="whitespace-pre overflow-x-auto p-4 bg-gray-900 text-green-400 rounded-lg">código aqui</pre> /* Badge que no se corta: */ <span class="whitespace-nowrap px-2 py-1 bg-gray-100 rounded">Badge</span>
text-ellipsis muestra puntos suspensivos al cortar (requiere overflow-hidden + whitespace-nowrap). whitespace-pre-wrap preserva el formato de código pero permite el corte de línea. whitespace-nowrap para badges y labels que no deben cortarse. overflow-x-auto + whitespace-pre para bloques de código con scroll horizontal.
Tipografía responsiva
/* Títulos escalables: */ <h1 class="text-3xl md:text-4xl lg:text-6xl font-bold"> Título Hero </h1> <h2 class="text-2xl md:text-3xl font-semibold"> Subtítulo </h2> /* Cuerpo de texto: */ <p class="text-base md:text-lg leading-relaxed text-gray-600"> Párrafo com boa legibilidad... </p> /* Regla: mobile 1 tamaño menor que desktop */ /* text-3xl → md:text-4xl → lg:text-5xl */
Tipografía responsiva: los títulos escalan con breakpoints — text-3xl md:text-4xl lg:text-6xl (menor en mobile, mayor en desktop). Cuerpo de texto: text-base md:text-lg con leading-relaxed para legibilidad. Regla práctica: mobile 1-2 tamaños menor que desktop. Evita texto menor que text-sm (14px) para el cuerpo. text-gray-600 para texto secundario.
Peso de la fuente
font-thin /* 100 */ font-extralight /* 200 */ font-light /* 300 */ font-normal /* 400 (por defecto) */ font-medium /* 500 */ font-semibold /* 600 */ font-bold /* 700 */ font-extrabold /* 800 */ font-black /* 900 */ /* Uso típico: */ <h1 class="text-4xl font-bold">Título principal</h1> <h2 class="text-2xl font-semibold">Subtítulo</h2> <p class="font-normal text-gray-600">Corpo de texto</p> <span class="text-sm font-medium">Label</span>
font-* define el peso de la fuente. font-bold (700) para títulos, font-semibold (600) para subtítulos y UI moderna, font-medium (500) para labels y botones, font-normal (400) para el cuerpo de texto. Asegúrate de que la fuente tenga los pesos necesarios — cárgalos desde Google Fonts con los pesos específicos para evitar FOUT.
Truncar y clamp
/* Una línea con puntos suspensivos: */ <p class="truncate">Texto muy largo que corta com puntos suspensivos...</p> /* Múltiples líneas (2-6): */ <p class="line-clamp-3">Texto que corta tras 3 lineas e mostra puntos suspensivos no fin da tercera linea...</p> /* Corte de palabras: */ break-words /* corta palabras largas (URLs) */ break-all /* corta en cualquier carácter */ whitespace-nowrap /* nunca corta (badges, labels) */ whitespace-pre-line /* preserva \n del texto */ /* line-clamp requiere display: -webkit-box (automático) */
truncate = una línea con puntos suspensivos (atajo para overflow-hidden + text-ellipsis + whitespace-nowrap). line-clamp-3 = corta tras N líneas con puntos suspensivos (requiere display box — automático en Tailwind). break-words evita el overflow de URLs largas. whitespace-nowrap impide el corte (badges, labels, fechas).
Text transform e indent
/* Transformación: */ uppercase /* MAYÚSCULAS */ lowercase /* minúsculas */ capitalize /* Primera Letra De Cada Palabra */ normal-case /* normal (quita la transformación) */ /* Indentación: */ indent-4 /* text-indent: 1rem */ indent-8 /* text-indent: 2rem */ -indent-4 /* negativo */ /* Guiones: */ hyphens-none | hyphens-manual | hyphens-auto /* Label clásico: */ <p class="uppercase tracking-wide text-sm font-semibold text-gray-500"> Categoria </p>
uppercase + tracking-wide + text-sm + font-semibold = patrón clásico para labels, badges y categorías. capitalize para títulos. indent-* añade indentación en la primera línea (texto editorial). hyphens-auto para texto justificado en columnas estrechas (requiere lang en el HTML).
Prose (plugin typography)
/* Plugin: @tailwindcss/typography */ <article class="prose prose-lg"> <h1>Título do artigo</h1> <p>Párrafo com formato automática...</p> <ul><li>Item 1</li><li>Item 2</li></ul> <blockquote>Cita</blockquote> <pre><code>código</code></pre> </article> /* Tamaños: prose-sm, prose, prose-lg, prose-xl, prose-2xl */ /* Colores: prose-slate, prose-gray, prose-zinc */ /* Dark: dark:prose-invert */ <article class="prose dark:prose-invert max-w-prose">
El plugin @tailwindcss/typography añade la clase prose que estiliza automáticamente contenido HTML rico (markdown, CMS, WYSIWYG). Aplica una tipografía bonita a h1-h6, p, ul, blockquote, pre, table. Tamaños: prose-sm a prose-2xl. dark:prose-invert para dark mode. Esencial para blogs y documentación.
Estilo y decoración
italic /* itálica */ not-italic /* quita la itálica */ underline /* subrayado */ overline /* línea arriba */ line-through /* tachado (precio antiguo) */ no-underline /* sin decoración (links) */ /* Subrayado estilizado: */ class="underline underline-offset-4 decoration-blue-500 decoration-2" /* Mayúsculas/minúsculas: */ uppercase | lowercase | capitalize | normal-case /* Precio con descuento: */ <span class="line-through text-gray-400">€99</span> <span class="font-bold text-green-600">€49</span>
italic/not-italic controlan el estilo de la fuente. underline, line-through (tachado — precios antiguos), no-underline (quita el subrayado de los links). underline-offset-4 aleja el subrayado del texto. decoration-blue-500 decoration-2 cambia color y grosor. uppercase para labels y badges.
Font family
font-sans /* ui-sans-serif, system-ui, -apple-system, ... */
font-serif /* ui-serif, Georgia, Cambria, ... */
font-mono /* ui-monospace, SFMono-Regular, Menlo, ... */
/* Custom (config v3): */
fontFamily: { display: ['Clash Display', 'sans-serif'] }
/* Uso: class="font-display" */
/* v4 (@theme): */
--font-display: 'Clash Display', sans-serif;
/* Uso: */
<h1 class="font-display text-5xl font-bold">Título custom</h1>
<code class="font-mono text-sm bg-gray-100 px-2 py-1 rounded">npm install</code>font-sans (por defecto en Tailwind), font-serif, font-mono son las familias base. Para fuentes custom, defínelas en fontFamily (v3) o --font-* (v4). font-mono para código, comandos y datos técnicos. Carga las fuentes vía Google Fonts (<link>) o @font-face en el CSS. Especifica siempre fallbacks.
Font variant y features
/* Numeros: */ tabular-nums /* numeros monoespaciados (tablas) */ lining-nums /* numeros alineados */ oldstyle-nums /* numeros antiguos (descendentes) */ /* Variantes: */ normal-nums ordinal /* 1º, 2º, 3º */ slashed-zero /* 0 con barra (distingue de O) */ /* Font features (OpenType): */ [font-feature-settings:'ss01','cv01'] /* Tabla de valores: */ <td class="tabular-nums text-right">€1.234,56</td> <td class="tabular-nums text-right">€99,00</td>
tabular-nums = numeros con ancho fijo — esencial para tablas de valores, timers, contadores y datos financieros (los dígitos se alinean en columnas). ordinal para indicadores ordinales (1º, 2º). slashed-zero distingue 0 de O (códigos, seriales). font-feature-settings vía valor arbitrario para features OpenType avanzadas.
Alineación de texto
text-left /* izquierda (por defecto LTR) */ text-center /* centrado */ text-right /* derecha */ text-justify /* justificado */ /* Responsivo: */ class="text-center md:text-left" /* Vertical (elementos inline/table-cell): */ align-baseline | align-top align-middle | align-bottom align-text-top | align-text-bottom /* Icono alineado con texto: */ <span>Texto <svg class="inline align-middle size-4">...</svg></span>
text-center para títulos, CTAs y hero sections. text-left para el cuerpo de texto (más legible). Responsivo: text-center md:text-left = centrado en mobile, izquierda en desktop. align-* alinea elementos inline verticalmente: align-middle para iconos al lado del texto. text-justify para texto en columnas estrechas (con hyphens-auto).
Listas
list-none /* sin marcador (menús, nav) */
list-disc /* puntos (por defecto en ul) */
list-decimal /* numeros (por defecto en ol) */
list-inside /* marcador dentro del padding */
list-outside /* marcador fuera (por defecto) */
/* Lista con estilo: */
<ul class="list-disc list-inside space-y-2 text-gray-700">
<li>Primero item</li>
<li>Segundo item</li>
<li>Terceiro item</li>
</ul>
/* Lista custom (sin marcador, con icono): */
<ul class="space-y-2">
<li class="flex items-center gap-2">
<svg class="size-4 text-green-500">✓</svg> Item
</li>
</ul>list-none quita los marcadores (menús, navegación). list-disc/list-decimal restauran los marcadores por defecto (el preflight los quita). list-inside coloca el marcador dentro del padding. Para listas custom con iconos, usa list-none + flex items-center gap-2 con un SVG. space-y-2 espacia los items.
Placeholder y selección
/* Placeholder: */ <input class="placeholder:text-gray-400 placeholder:italic" placeholder="Escribe aqui..."> /* Selección de texto: */ <p class="selection:bg-blue-200 selection:text-blue-900"> Texto com selección customizada </p> /* Caret (cursor del input): */ <input class="caret-blue-500"> /* Combinación en un input: */ <input class="w-full px-4 py-2 rounded-lg border placeholder:text-gray-400 caret-blue-600 selection:bg-blue-100 focus:ring-2 focus:ring-blue-500">
placeholder:text-gray-400 estiliza el placeholder (variante placeholder:). selection:bg-* cambia el color de selección de texto (detalle de polish). caret-* cambia el color del cursor en el input. Son detalles sutiles que mejoran la experiencia visual y muestran atención al detalle. Combina con focus:ring-2 para un input completo.
Cores e Backgrounds
Color de texto
text-red-500 text-blue-600 text-green-700 text-gray-900 text-white text-black text-transparent /* Opacidad: */ text-red-500/50 /* 50% de opacidad */ text-black/75 /* Color arbitrario: */ text-[#1fb6ff] text-[rgb(31,182,255)] /* Jerarquía típica: */ <h1 class="text-gray-900">Título</h1> <p class="text-gray-600">Corpo</p> <span class="text-gray-400">Secundario</span>
text-{color}-{tono} define el color del texto. Escala de 50 (muy claro) a 950 (muy oscuro). text-white/text-black para los extremos. /50 añade opacidad (50%). text-transparent para texto invisible (con bg-clip-text para gradientes). Jerarquía: text-gray-900 (títulos), text-gray-600 (cuerpo), text-gray-400 (secundario).
Opacidad
opacity-0 /* invisible */ opacity-5 /* 5% */ opacity-25 /* 25% */ opacity-50 /* 50% */ opacity-75 /* 75% */ opacity-100 /* total (por defecto) */ /* Color con alpha (sintaxis /): */ bg-black/50 /* fondo negro 50% */ text-white/75 /* texto blanco 75% */ border-gray-200/50 /* Hover con opacidad: */ class="opacity-70 hover:opacity-100 transition-opacity" /* Overlay de modal: */ <div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
opacity-* controla la transparencia del elemento ENTERO (incluidos los hijos). /50 en el color añade alpha solo al color (sin afectar a los hijos). bg-black/50 para overlays de modal. opacity-70 hover:opacity-100 + transition-opacity para un efecto hover sutil en imágenes e iconos. Prefiere /alpha en el color cuando quieres transparencia sin afectar al contenido.
Outline
outline-none /* quita el outline */ outline /* outline sólido */ outline-dashed outline-dotted outline-2 /* grosor */ outline-blue-500 /* color */ outline-offset-2 /* distancia del elemento */ /* Accesibilidad (focus visible solo con teclado): */ <button class="focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2"> /* NUNCA: focus:outline-none sin alternativa */
outline-* estiliza el contorno (no afecta al layout, a diferencia de border). focus-visible:outline se muestra solo al navegar con teclado (mejor que focus:outline-none que quita la accesibilidad). outline-offset-2 aleja el contorno del elemento. NUNCA quites el focus sin alternativa — usa focus:ring-2 o focus-visible:outline para mantener la accesibilidad.
Color de fondo
bg-blue-500
bg-gray-100
bg-white
bg-black
bg-transparent
bg-inherit
bg-current /* color del texto actual */
/* Opacidad: */
bg-blue-500/75
bg-black/50
/* Color arbitrario: */
bg-[#1fb6ff]
/* Imagen de fondo: */
bg-[url('/img/pattern.png')]
/* Overlay oscuro sobre imagen: */
<div class="bg-black/50 absolute inset-0"></div>bg-{color}-{tono} define el fondo. bg-white/bg-gray-100 para fondos claros. /75 = 75% de opacidad (overlays). bg-current usa el color del texto (útil para iconos SVG que heredan el color). bg-[url(...)] para imágenes de fondo arbitrarias. bg-black/50 para overlays oscuros sobre imágenes (mejora la legibilidad del texto).
Border color
border-gray-300 border-blue-500 border-red-200 border-transparent border-current /* color del texto */ border-inherit /* Lados específicos: */ border-t-gray-200 /* solo arriba */ border-b-blue-500 /* solo abajo */ /* Opacidad: */ border-gray-300/50 /* Ejemplo: card con borde sutil */ <div class="border border-gray-200 rounded-lg p-4"> /* Separador: */ <hr class="border-t border-gray-200">
border-{color} define el color del borde. border-t-*/border-b-* para lados específicos (separadores, subrayados). border-transparent para bordes invisibles (mantener espacio para el hover). border-current usa el color del texto (iconos con borde). Combina con border (1px) o border-2 para el grosor. border-gray-200 es el estándar para bordes sutiles.
Background image y size
bg-cover /* rellena (recorta el exceso) */
bg-contain /* cabe todo (puede tener barras) */
bg-auto /* tamaño original */
bg-center /* centrado */
bg-top, bg-bottom, bg-left, bg-right
bg-no-repeat /* sin repetición */
bg-fixed /* parallax (fijo al scroll) */
bg-local /* scroll con el contenido */
/* Hero con imagen de fondo: */
<div class="bg-cover bg-center bg-no-repeat h-96"
style="background-image: url('hero.jpg')">
<div class="bg-black/50 h-full flex items-center">
<h1 class="text-white text-4xl">Título</h1>
</div>
</div>bg-cover + bg-center = imagen de fondo que rellena sin distorsionar (recorta el exceso). bg-no-repeat evita la repetición. bg-fixed para un efecto parallax. Define la imagen vía style inline o bg-[url(...)]. Combina con un overlay bg-black/50 para la legibilidad del texto sobre la imagen. Patrón esencial para hero sections.
Paleta de colores por defecto
/* Neutros (5 opciones): */ slate (azulado) | gray (neutro) | zinc (cálido) neutral (puro) | stone (terroso) /* Colores (17): */ red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose /* Escala por color (11 tonos): */ 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 /* Total: 22 colores × 11 tonos = 242 colores */
22 colores × 11 tonos = 242 colores disponibles. Neutros: slate (azulado, moderno), gray (neutro, versátil), zinc (cálido), stone (terroso). Escala: 50 (muy claro, fondos) → 500 (base, acciones) → 950 (muy oscuro, texto). Usa 500/600 para botones, 100/200 para fondos, 700/900 para texto.
Ring (anillo de focus)
ring-1, ring-2, ring-4, ring-8, ring ring-blue-500 ring-offset-2 ring-offset-white /* Focus state (accesibilidad): */ <button class="focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"> /* Anillo decorativo (avatar): */ <img class="ring-4 ring-blue-300 rounded-full" src="avatar.jpg"> /* Ring en hover: */ <div class="hover:ring-2 hover:ring-blue-400 transition">
ring-* crea un anillo (vía box-shadow) alrededor del elemento — no afecta al layout. ring-offset-2 añade espacio entre el elemento y el anillo. Esencial para focus:ring-2 (accesibilidad — sustituye el outline por defecto). ring-4 ring-blue-300 para avatares destacados. Combina con ring-offset-white en fondos oscuros.
bg-clip y mix-blend
/* Clip (recorte del fondo): */ bg-clip-border bg-clip-padding bg-clip-content bg-clip-text /* fondo visible solo en el texto */ /* Texto con gradiente: */ <h1 class="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">Título com gradiente</h1> /* Blend modes: */ mix-blend-multiply /* oscurece */ mix-blend-screen /* aclara */ mix-blend-overlay /* contrasta */ mix-blend-difference /* invierte */ /* Overlay creativo: */ <div class="bg-blue-600 mix-blend-multiply">
bg-clip-text + text-transparent = texto con gradiente o imagen de fondo (muy popular en hero sections). mix-blend-* aplica blend modes (como Photoshop): multiply oscurece, screen aclara, overlay contrasta. Útil para overlays creativos, efectos de imagen y composiciones visuales avanzadas.
Gradientes
<div class="bg-gradient-to-r from-blue-500 to-purple-600"> /* Direcciones: */ bg-gradient-to-r /* → derecha */ bg-gradient-to-l /* ← izquierda */ bg-gradient-to-t /* ↑ arriba */ bg-gradient-to-b /* ↓ abajo */ bg-gradient-to-tr /* ↗ diagonal */ bg-gradient-to-br /* ↘ diagonal */ /* Parada intermedia: */ class="bg-gradient-to-r from-cyan-500 via-blue-500 to-purple-600" /* Gradiente de texto: */ class="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
bg-gradient-to-* define la dirección del gradiente. from-* = color inicial, to-* = color final, via-* = parada intermedia (3+ colores). Para texto con gradiente: bg-clip-text text-transparent + gradiente en el fondo. Combina con hover:from-* para animar el color inicial en el hover. Los gradientes son populares en hero sections y botones CTA.
Divide (separadores entre hijos)
divide-y /* línea horizontal entre hijos */ divide-x /* línea vertical entre hijos */ divide-y-2 /* 2px de grosor */ divide-gray-200 /* color */ divide-dashed /* discontinuo */ divide-y-reverse /* Lista con separadores: */ <ul class="divide-y divide-gray-200"> <li class="py-3">Item 1</li> <li class="py-3">Item 2</li> <li class="py-3">Item 3</li> </ul> /* Ventaja: sin borde en el último item */
divide-y añade bordes entre los hijos (sin tocar el primero/último). divide-gray-200 define el color. divide-dashed para discontinuo. Sustituye border-b en cada item (más limpio, sin borde en el último). Ideal para listas, feeds, tablas y cualquier stack vertical con separadores. divide-x para separadores verticales (botones lado a lado).
Colores semánticos (estados)
/* Éxito: */ class="bg-green-100 text-green-800 border-green-200" /* Error: */ class="bg-red-100 text-red-800 border-red-200" /* Aviso: */ class="bg-amber-100 text-amber-800 border-amber-200" /* Info: */ class="bg-blue-100 text-blue-800 border-blue-200" /* Neutro: */ class="bg-gray-100 text-gray-800 border-gray-200" /* Patrón: fondo claro (100) + texto oscuro (800) + borde (200) */
Colores semánticos para estados: green (éxito), red (error), amber (aviso), blue (info), gray (neutro). Patrón consistente: fondo claro (100) + texto oscuro (800) + borde sutil (200). Garantiza un contraste legible sin ser agresivo. Úsalo en alertas, badges, toasts y mensajes de validación.
Bordas e Efeitos
Border (estilo y grosor)
border /* 1px todos los lados */ border-2 /* 2px */ border-4 /* 4px */ border-8 /* 8px */ border-0 /* quita */ border-t /* solo arriba (1px) */ border-b-2 /* solo abajo (2px) */ border-x /* izquierda + derecha */ border-y /* arriba + abajo */ /* Estilo: */ border-solid | border-dashed | border-dotted border-double | border-none /* Card con borde sutil: */ <div class="border border-gray-200 rounded-lg p-4">
border = 1px sólido en todos los lados (el más usado). border-2/border-4 para más grosor. border-t/border-b para lados específicos (separadores, subrayados). border-dashed/border-dotted para estilos alternativos. Combina con border-gray-200 para un color sutil. El preflight quita los bordes por defecto — añádelos explícitamente.
Transformaciones
/* Escala: */ scale-105, scale-95, scale-0, scale-150 scale-x-50, scale-y-110 /* Rotación: */ rotate-45, rotate-90, rotate-180 -rotate-12 /* Traslación: */ translate-x-4, -translate-y-2 translate-x-1/2, -translate-x-1/2 /* Skew: */ skew-x-3, -skew-y-6 /* Hover (zoom en card): */ class="hover:scale-105 transition-transform duration-300" /* Icono que rota: */ class="group-hover:rotate-90 transition-transform"
scale-105 = 105% (hover en cards, zoom sutil). rotate-45 = 45° (flechas, iconos). translate-x-1/2 = desplaza 50% (centrado con absolute). skew-* para efectos inclinados. Valores negativos con -. Combina con transition-transform para animar. hover:scale-110 = zoom en el hover (imágenes, cards).
Cursor y resize
cursor-pointer /* mano (links/botones) */ cursor-default /* flecha normal */ cursor-not-allowed /* prohibido (disabled) */ cursor-wait /* reloj de arena (loading) */ cursor-text /* texto (inputs) */ cursor-move /* mover (drag) */ cursor-grab /* agarrar */ cursor-grabbing /* arrastrando */ cursor-zoom-in cursor-crosshair /* Resize (textareas): */ resize-none | resize | resize-x | resize-y /* Botón disabled: */ <button disabled class="cursor-not-allowed opacity-50">
cursor-pointer para elementos clicables (Tailwind lo quita del button por defecto en el preflight). cursor-not-allowed para estados disabled. cursor-grab/grabbing para drag & drop. resize-none quita el resize de los textareas (estándar en UI custom). resize-y solo permite resize vertical. Combina con disabled:opacity-50.
Border radius
rounded-none /* 0 (sharp) */ rounded-sm /* 0.125rem (2px) */ rounded /* 0.25rem (4px) — por defecto */ rounded-md /* 0.375rem (6px) */ rounded-lg /* 0.5rem (8px) */ rounded-xl /* 0.75rem (12px) */ rounded-2xl /* 1rem (16px) */ rounded-3xl /* 1.5rem (24px) */ rounded-full /* 9999px (círculo/píldora) */ /* Lados específicos: */ rounded-t-lg /* solo arriba */ rounded-b-none /* quita abajo */ rounded-l-full /* solo izquierda */ rounded-tr-xl /* solo esquina superior derecha */
rounded = 0.25rem (por defecto). rounded-lg/rounded-xl para cards modernos. rounded-full = círculo (avatares) o píldora (botones, badges). rounded-t-*/rounded-b-* para lados específicos (cards con imagen arriba). rounded-none lo quita (estilo sharp/brutalist). rounded-tr-xl para esquinas individuales.
Animaciones
animate-spin /* rotación continua (loading) */ animate-ping /* pulsa y expande (notificación) */ animate-pulse /* pulsa la opacidad (skeleton) */ animate-bounce /* rebota (atención) */ animate-none /* quita la animación */ /* Loading spinner: */ <span class="animate-spin inline-block size-6 border-4 border-gray-300 border-t-blue-600 rounded-full"></span> /* Notificación (punto pulsante): */ <span class="relative"> <span class="animate-ping absolute size-3 bg-red-500 rounded-full"></span> <span class="relative size-3 bg-red-500 rounded-full"></span> </span>
animate-spin para spinners de loading. animate-ping para notificaciones (pulsa y expande — combina con un punto estático encima). animate-pulse para skeleton loading (bloques grises que pulsan). animate-bounce para llamar la atención (flechas de scroll). Spinner: border-4 border-t-blue-600 rounded-full animate-spin. Para animaciones custom, usa @keyframes en el CSS.
Scroll behavior y snap
/* Smooth scroll: */ scroll-smooth /* scroll suave (anclas) */ scroll-auto /* instantáneo */ /* Scroll snap: */ snap-x /* snap horizontal */ snap-y /* snap vertical */ snap-mandatory /* obligatorio */ snap-proximity /* por proximidad */ snap-start, snap-center, snap-end snap-none /* Carrusel nativo (sin JS): */ <div class="flex overflow-x-auto snap-x snap-mandatory"> <div class="snap-center shrink-0 w-full">Slide 1</div> <div class="snap-center shrink-0 w-full">Slide 2</div> <div class="snap-center shrink-0 w-full">Slide 3</div> </div>
scroll-smooth en el html para scroll suave en anclas (links #seccion). snap-x snap-mandatory + snap-center en los hijos = un carrusel nativo sin JavaScript. snap-proximity = snap solo cuando está cerca. shrink-0 impide que los slides encojan. Alternativa moderna y performante a las librerías de slider (Swiper, Slick).
Sombras (box-shadow)
shadow-sm /* sutil (cards planos) */ shadow /* por defecto */ shadow-md /* medio (dropdowns) */ shadow-lg /* grande (modales) */ shadow-xl /* extra */ shadow-2xl /* máximo (hero) */ shadow-inner /* interna (inputs presionados) */ shadow-none /* quita */ /* Color de la sombra: */ shadow-blue-500/50 shadow-lg shadow-blue-500/25 /* Hover (elevación): */ class="shadow hover:shadow-lg transition-shadow duration-300"
shadow = sombra por defecto. shadow-sm sutil (cards planos), shadow-lg pronunciada (dropdowns, modales). shadow-inner = inset (inputs presionados, wells). Color: shadow-blue-500/25 para sombras de color. Hover: hover:shadow-lg transition-shadow para un efecto de elevación (el card "sube"). Esencial para la profundidad y la jerarquía visual.
Filters (imagen)
/* Blur: */ blur-sm, blur, blur-md, blur-lg, blur-xl /* Brillo/contraste: */ brightness-50, brightness-100, brightness-150 contrast-50, contrast-100, contrast-200 /* Saturación: */ saturate-0, saturate-100, saturate-200 /* Grayscale/Sepia/Invert: */ grayscale, sepia, invert, hue-rotate-90 /* Hover (foto de equipo): */ class="grayscale hover:grayscale-0 transition duration-300" /* Imagen oscurecida: */ class="brightness-75 hover:brightness-100 transition"
blur-* desenfoca (overlays, fondos de modal). brightness-50 oscurece, brightness-150 aclara. grayscale + hover:grayscale-0 = efecto clásico en fotos de equipo (gris → color en el hover). saturate-0 = sin color. Combina con transition para animar los filtros en el hover. Esencial para galerías y portfolios.
Will-change y rendimiento
will-change-auto
will-change-scroll /* scroll-position */
will-change-contents /* contents */
will-change-transform /* transform */
/* GPU acceleration: */
transform-gpu /* translateZ(0) — fuerza una capa GPU */
transform-none
/* Backface (flip cards 3D): */
backface-visible
backface-hidden /* esconde el reverso */
/* Flip card: */
<div class="[perspective:1000px]">
<div class="transition-transform duration-500
[transform-style:preserve-3d] hover:[transform:rotateY(180deg)]">
<div class="[backface-visibility:hidden]">Frente</div>
<div class="[transform:rotateY(180deg)] [backface-visibility:hidden]">Verso</div>
</div>
</div>will-change-transform avisa al browser para que optimice (crea una capa GPU). Úsalo con moderación — solo en elementos que vayan a animarse. transform-gpu fuerza la aceleración GPU. backface-hidden para flip cards 3D (esconde el reverso al rotar). Quita will-change tras la animación para liberar memoria. Un flip card usa perspective + preserve-3d + rotateY.
Transiciones
transition /* propiedades comunes (color, sombra, transform) */ transition-all /* todas las propiedades */ transition-colors /* colores (bg, text, border) */ transition-transform /* solo transform */ transition-opacity transition-shadow transition-none /* Duración y easing: */ duration-150, duration-200, duration-300, duration-500 ease-linear, ease-in, ease-out, ease-in-out /* Botón con transición suave: */ <button class="transition-colors duration-200 hover:bg-blue-700 active:bg-blue-800">
transition anima propiedades comunes (colores, sombras, transforms, opacity). transition-colors = solo colores (más performante que transition-all). duration-200 = 200ms (ideal para UI). ease-in-out = aceleración suave. Combina siempre con un estado (hover:, focus:). Sin transition, el cambio es instantáneo (sin animación).
Backdrop filter
backdrop-blur-sm backdrop-blur backdrop-blur-md backdrop-blur-lg backdrop-blur-xl backdrop-brightness-50 backdrop-saturate-150 /* Navbar con vidrio esmerilado (glassmorphism): */ <nav class="fixed top-0 w-full bg-white/70 backdrop-blur-md border-b border-gray-200/50 z-50"> Menu </nav> /* Modal overlay: */ <div class="fixed inset-0 bg-black/30 backdrop-blur-sm">
backdrop-blur-* desenfoca el contenido DETRÁS del elemento (efecto vidrio esmerilado / glassmorphism). Combina con bg-white/70 (fondo semi-transparente) — sin opacidad, el blur no se ve. backdrop-brightness-50 oscurece el fondo. Popular en navbars, modales y overlays modernos. Requiere un bg-* con opacidad para que el efecto funcione.
Efecto glassmorphism
/* Card con vidrio esmerilado: */ <div class="bg-white/20 backdrop-blur-lg border border-white/30 rounded-2xl shadow-xl p-6"> Contenido glassmorphism </div> /* Navbar glass: */ <nav class="bg-white/70 backdrop-blur-md border-b border-gray-200/50 shadow-sm"> /* Glass en dark mode: */ <div class="bg-gray-900/50 backdrop-blur-xl border border-white/10 rounded-xl"> /* Requiere: bg con opacidad + backdrop-blur + borde sutil */
Glassmorphism (vidrio esmerilado): combina bg-white/20 (fondo semi-transparente) + backdrop-blur-lg (desenfoque) + border border-white/30 (borde sutil) + rounded-2xl shadow-xl. Funciona sobre imágenes o gradientes de color. En dark mode: bg-gray-900/50 + border-white/10. Popular en navbars, cards y overlays modernos (estilo macOS/iOS).
Responsivo e Estados
Breakpoints
sm: /* ≥ 640px (móvil landscape) */ md: /* ≥ 768px (tablet) */ lg: /* ≥ 1024px (desktop pequeño) */ xl: /* ≥ 1280px (desktop) */ 2xl: /* ≥ 1536px (pantalla grande) */ /* Mobile-first: */ class="w-full md:w-1/2 lg:w-1/3" /* Por defecto es mobile-first: */ /* base = mobile (todos los tamaños) */ /* prefijo = sobrescribe a partir de ese breakpoint */ /* NO existe prefijo xs (base = mobile) */
Mobile-first: las clases sin prefijo se aplican en TODOS los tamaños; con prefijo, sobrescriben a partir de ese breakpoint. w-full md:w-1/2 = 100% en mobile, 50% en md+. No existe prefijo xs — la base ES el mobile. Los breakpoints son configurables en el tema (v3) o vía --breakpoint-* (v4). Piensa "a partir de" y no "hasta".
group (el padre controla a los hijos)
<div class="group cursor-pointer">
<h3 class="text-gray-900 group-hover:text-blue-600
transition-colors">
Título
</h3>
<p class="text-gray-500 group-hover:text-gray-700">
Descripcion
</p>
<span class="opacity-0 group-hover:opacity-100
transition-opacity">
→ Ver mais
</span>
</div>
/* group-focus, group-active, group-hover */
/* Nombrado: group/card + group-hover/card: */group en el padre + group-hover:* en el hijo = el hijo reacciona al hover del PADRE. Útil para cards: al hacer hover en el card cambia el color del título, muestra una flecha, eleva la sombra. group-focus:, group-active: también funcionan. Para grupos anidados, nómbralos: group/card + group-hover/card: (evita conflictos). Esencial para componentes interactivos.
Container queries (v3.2+)
/* Plugin: @tailwindcss/container-queries */
<div class="@container">
<div class="grid grid-cols-1 @lg:grid-cols-3">
<div>Sidebar</div>
<div class="@lg:col-span-2">Contenido</div>
</div>
</div>
/* Breakpoints: @sm, @md, @lg, @xl, @2xl */
/* Basados en el ancho del PADRE, no del viewport */
/* v4 (nativo, sin plugin): */
@container
@min-[400px]:flex-row
/* Nombrado: @container/sidebar + @lg/sidebar: */@container en el padre + @lg:* en el hijo = estilos basados en el ancho del CONTENEDOR (no del viewport). Ideal para componentes reutilizables: un card en la sidebar (estrecha) vs. en el main (ancho) se adapta automáticamente. @sm, @md, @lg son los breakpoints. En v4, las container queries son nativas (sin plugin). Nómbralas con @container/nombre para múltiples containers.
Breakpoints custom
/* v3 (config): */
theme: {
screens: {
'xs': '475px',
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
'3xl': '1920px',
}
}
/* v4 (CSS): */
@theme {
--breakpoint-xs: 475px;
--breakpoint-3xl: 1920px;
}
/* Uso: xs:text-sm, 3xl:text-2xl */Breakpoints custom: añade xs (475px) para móviles pequeños o 3xl (1920px) para pantallas grandes. En v3, defínelos en theme.screens (sustituye) o theme.extend.screens (añade). En v4, usa --breakpoint-* en @theme. Uso: xs:text-sm, 3xl:text-2xl. Mantén los valores por defecto y añade solo lo necesario.
Estados (hover/focus/active)
<button class="bg-blue-500 text-white px-4 py-2 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 active:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"> Clica </button> /* Estados disponibles: */ hover: | focus: | focus-within: | focus-visible: active: | visited: | disabled: | checked: first: | last: | odd: | even: | empty: required: | valid: | invalid: | read-only:
hover: = al pasar el ratón. focus:ring-2 = accesibilidad (navegación con teclado). active: = al hacer clic/presionar. disabled:opacity-50 = estado desactivado. focus-visible: = solo al navegar con teclado (mejor UX que focus:). Usa siempre transition para suavizar los cambios de estado. Nunca quites el focus sin alternativa.
peer (hermano anterior)
/* Toggle custom: */
<input class="peer sr-only" type="checkbox" id="toggle">
<label for="toggle"
class="block w-12 h-6 bg-gray-300 rounded-full
peer-checked:bg-blue-600 transition-colors">
</label>
/* Validación: */
<input class="peer" type="email">
<p class="hidden peer-invalid:block text-red-500">Inválido</p>
/* Nombrado (múltiples peers): */
<input class="peer/input">
<span class="peer-checked/input:text-blue-600">
/* El peer DEBE ir ANTES del elemento estilizado en el DOM */peer en el elemento anterior + peer-checked:* en el siguiente = el siguiente reacciona al estado del anterior. Esencial para toggles custom (checkbox + label), validación visual (peer-invalid:), e inputs con labels flotantes. El peer debe ir ANTES del elemento estilizado en el DOM. Para múltiples peers, nómbralos: peer/input + peer-checked/input:.
RTL y direcciones lógicas
/* Lógico (RTL-aware): */ ms-4 /* margin-start (izq en LTR, der en RTL) */ me-4 /* margin-end */ ps-4 /* padding-start */ pe-4 /* padding-end */ start-0 /* left en LTR, right en RTL */ end-0 /* right en LTR, left en RTL */ text-start | text-end /* Físico (fijo): */ ml-4, mr-4, pl-4, pr-4, left-0, right-0 text-left, text-right /* Variante RTL: */ rtl:space-x-reverse rtl:text-right
Las propiedades lógicas (ms, me, ps, pe, start, end) se adaptan automáticamente a RTL (árabe, hebreo). Prefiere las lógicas en código nuevo para la internacionalización. rtl:space-x-reverse invierte el espaciado en RTL. text-start/text-end sustituyen a text-left/text-right. Esencial para apps multi-idioma.
Dark mode
/* config v3: */
darkMode: 'class' /* o 'media' (por defecto) */
/* v4: por defecto = media; para class: */
@custom-variant dark (&:where(.dark, .dark *));
/* Uso (pares light/dark): */
<div class="bg-white text-gray-900
dark:bg-gray-900 dark:text-white
dark:border-gray-700">
Contenido
</div>
/* Toggle vía JS: */
document.documentElement.classList.toggle('dark')
/* Define siempre PARES: bg-white dark:bg-gray-900 */dark: aplica estilos en el tema oscuro. darkMode: 'class' (v3) = controlado por la clase .dark en el html. 'media' (por defecto) = sigue el prefers-color-scheme del sistema operativo. En v4, usa @custom-variant para el modo class. Define siempre pares: bg-white dark:bg-gray-900. Incluye los bordes: border-gray-200 dark:border-gray-700.
Variantes de hijo y posición
/* Primer/último hijo: */ first:pt-0 last:pb-0 last:border-0 /* Odd/even (filas alternadas): */ odd:bg-gray-50 even:bg-white /* Hijo único: */ only:rounded-lg /* Vacío: */ empty:hidden /* Lista con separadores y padding ajustado: */ <ul class="divide-y divide-gray-200"> <li class="py-3 first:pt-0 last:pb-0">Item</li> </ul> /* Tabla con filas alternadas: */ <tr class="odd:bg-gray-50 even:bg-white">
first:, last:, odd:, even:, only:, empty: son variantes de posición/estado del elemento. first:pt-0 last:pb-0 quita el padding extra al inicio/fin de las listas. odd:bg-gray-50 = filas alternadas (tablas). last:border-0 quita el borde del último item. empty:hidden oculta los elementos vacíos.
Print y motion
/* Print: */ print:hidden /* oculto al imprimir */ print:block /* visible solo al imprimir */ print:text-black /* texto negro al imprimir */ print:shadow-none /* sin sombras */ /* Motion (respeta las preferencias del usuario): */ motion-safe:animate-bounce motion-reduce:transition-none motion-reduce:animate-none /* Botón con animación accesible: */ <button class="motion-safe:hover:scale-105 motion-reduce:hover:scale-100 transition"> /* Respeta el prefers-reduced-motion del SO */
print:hidden oculta elementos al imprimir (nav, botones, sidebars). print:text-black fuerza texto negro (ahorra tinta). motion-safe: aplica animaciones solo si el usuario no pidió movimiento reducido. motion-reduce: quita las animaciones para quien lo prefiere. Esencial para la accesibilidad (trastornos vestibulares, epilepsia). Respeta prefers-reduced-motion.
Mostrar/ocultar responsivo
/* Ocultar en mobile, mostrar en md+: */ hidden md:block /* Mostrar solo en mobile: */ block md:hidden /* Visibilidad (mantiene el espacio): */ visible | invisible /* Menú desktop + hamburguesa mobile: */ <nav class="hidden md:flex gap-4"> <a href="#">Inicio</a> <a href="#">Sobre</a> </nav> <button class="md:hidden">☰</button> /* Sidebar: oculta en mobile */ <aside class="hidden lg:block w-64">Sidebar</aside>
hidden md:block = oculto en mobile, visible en md+. block md:hidden = visible solo en mobile. hidden = display: none (sale del flujo, no ocupa espacio). invisible = visibility: hidden (mantiene el espacio). Patrón clásico: nav hidden md:flex + botón hamburguesa md:hidden. Esencial para la navegación responsiva.
Variantes de data y ARIA
/* Data attributes: */ data-[state=open]:block data-[active=true]:text-blue-600 data-[side=top]:animate-in /* ARIA: */ aria-selected:bg-blue-100 aria-expanded:rotate-180 aria-hidden:true:invisible aria-invalid:border-red-500 aria-current:font-bold /* Accordion (el icono rota al expandir): */ <button aria-expanded="false" class="aria-expanded:rotate-180 transition-transform"> ▼ </button>
data-[state=open]: estiliza en base a atributos data-* (popular en Radix UI, Headless UI, Alpine.js). aria-expanded:rotate-180 rota el icono cuando está expandido (accordions). aria-invalid:border-red-500 para validación accesible. aria-current:font-bold para la navegación activa. Esencial para componentes accesibles con estados gestionados por JavaScript.
Responsivo completo (ejemplo)
<section class="py-8 md:py-16 lg:py-24">
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<h1 class="text-2xl md:text-4xl lg:text-5xl
font-bold text-center md:text-left">
Título
</h1>
<p class="mt-4 text-base md:text-lg text-gray-600
max-w-prose mx-auto md:mx-0">
Descripcion...
</p>
<div class="grid grid-cols-1 md:grid-cols-2
lg:grid-cols-3 gap-4 md:gap-8 mt-8 md:mt-12">
<div class="p-4 md:p-6 bg-white rounded-xl shadow">Card</div>
</div>
</div>
</section>Patrón responsivo completo: padding progresivo (py-8 md:py-16 lg:py-24), tipografía escalable (text-2xl md:text-4xl), grid adaptativo (grid-cols-1 md:grid-cols-2 lg:grid-cols-3), gap responsivo (gap-4 md:gap-8), alineación adaptable (text-center md:text-left). Mobile-first: define la versión mobile y sobrescribe en breakpoints mayores.
Avançado e Boas Práticas
@apply (componentes CSS)
/* input.css */
@layer components {
.btn {
@apply px-4 py-2 rounded-lg font-medium
transition-colors duration-200;
}
.btn-primary {
@apply btn bg-blue-600 text-white
hover:bg-blue-700;
}
.btn-outline {
@apply btn border-2 border-blue-600 text-blue-600
hover:bg-blue-50;
}
}
/* Uso: */
<button class="btn-primary">Ok</button>@apply extrae clases reutilizables en CSS. @layer components garantiza el orden correcto (no sobrescribe las utilities). Útil para botones, inputs y patrones repetidos en contenido sin componentes (Markdown, CMS, emails). PERO: prefiere componentes del framework (React/Vue/Blade) para la reutilización. @apply es para cuando necesitas clases en CSS puro.
tailwind-merge y clsx
import { twMerge } from 'tailwind-merge'
import { clsx } from 'clsx'
/* twMerge resuelve conflictos: */
twMerge('px-4 py-2', 'px-6') /* → 'py-2 px-6' */
twMerge('text-red-500', 'text-blue-500') /* → 'text-blue-500' */
/* clsx condicional: */
clsx('btn', { 'btn-active': isActive })
/* cn() = clsx + twMerge (patrón shadcn/ui): */
function cn(...inputs) {
return twMerge(clsx(inputs))
}
<div class={cn('p-4', isActive && 'bg-blue-50', className)}>tailwind-merge resuelve conflictos: twMerge('px-4', 'px-6') = px-6 (gana el último, sin duplicados). clsx compone clases condicionalmente. cn() = la combinación de ambos (el estándar en shadcn/ui). Esencial para componentes que aceptan una prop className y necesitan un merge sin conflictos. Sin esto, px-4 px-6 genera un comportamiento impredecible.
Debug y troubleshooting
/* 1. ¿Clase no funciona? Revisa el content: */ content: ["./resources/views/**/*.blade.php"] /* 2. Inspecciona con DevTools: */ /* - ¿La clase está en el CSS generado? */ /* - ¿Hay conflicto de especificidad? */ /* - ¿Hay otra clase que la sobrescribe? */ /* 3. Usa el plugin Debug Screens: */ /* Muestra el breakpoint activo en la esquina */ npm install -D @tailwindcss/debug-screens /* 4. Important (último recurso): */ class="!text-red-500" /* !important */ /* 5. Orden: la ÚLTIMA clase en el CSS gana */ /* (no la última en el HTML) */
Troubleshooting: 1) ¿La clase no aparece? Revisa el content en el config (el archivo puede no estar incluido). 2) Inspecciona con DevTools — ¿la clase está en el CSS generado? ¿Hay conflicto de especificidad? 3) @tailwindcss/debug-screens muestra el breakpoint activo. 4) El prefijo ! añade !important (último recurso). 5) El ORDEN en el CSS importa, no el orden en el HTML — gana la última clase generada.
@layer y @utility (v4)
/* v4: crear utilidades custom */
@utility scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
}
@utility text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
/* Uso (¡funciona con variantes!): */
<div class="scrollbar-hide hover:text-shadow md:text-shadow">
/* v3 (@layer): */
@layer utilities {
.scrollbar-hide { ... }
}
/* Layers: base < components < utilities */En v4, @utility crea utilidades custom que funcionan con variantes (hover:scrollbar-hide, md:text-shadow). En v3, usa @layer utilities (pero sin variantes automáticas). @layer components para clases compuestas. @layer base para reset/estilos globales. El orden de las layers importa: base < components < utilities.
Componentes Blade (Laravel)
{{-- resources/views/components/button.blade.php --}}
@props(['variant' => 'primary', 'size' => 'md'])
@php
$base = 'inline-flex items-center gap-2 rounded-lg
font-medium transition-colors focus:ring-2';
$variants = [
'primary' => 'bg-blue-600 text-white hover:bg-blue-700',
'outline' => 'border-2 border-blue-600 text-blue-600',
];
$sizes = ['sm' => 'px-3 py-1.5 text-sm',
'md' => 'px-4 py-2', 'lg' => 'px-6 py-3 text-lg'];
@endphp
<button {{ $attributes->class([$base,
$variants[$variant], $sizes[$size]]) }}>
{{ $slot }}
</button>
{{-- Uso: <x-button variant="outline" size="lg">Ok</x-button> --}}Componentes Blade reutilizables: define $base + arrays de variantes. Usa $attributes->class([]) para el merge de clases (Laravel hace el merge automáticamente). Props con defaults: @props(['variant' => 'primary']). Uso: <x-button variant="outline" size="lg">. Una alternativa al @apply — más flexible y con soporte de variantes. El patrón recomendado en Laravel.
Performance y producción
/* 1. Tree-shaking (automático): */ /* Solo se generan las clases usadas en el HTML */ /* Proyecto grande: ~10-30kb de CSS final */ /* 2. PurgeCSS (v3 — automático vía content) */ /* 3. Minificación: */ npx tailwindcss -i input.css -o output.css --minify /* 4. Evita transition-all (específico es mejor): */ transition-colors /* bueno */ transition-all /* pesado (todas las props) */ /* 5. will-change con moderación */ /* 6. Lazy load de imágenes: */ <img loading="lazy" class="..." src="foto.jpg">
Performance: 1) tree-shaking automático — solo se generan las clases usadas (10-30kb final). 2) Minifica con --minify o vite build. 3) Prefiere transition-colors a transition-all (menos propiedades animadas = mejor performance). 4) will-change con moderación (crea layers GPU). 5) loading="lazy" en imágenes debajo del fold. 6) Evita el @apply excesivo (genera CSS duplicado).
Buenas prácticas
/* 1. Mobile-first: base → sm → md → lg */
class="flex-col md:flex-row"
/* 2. Componentes en el framework (no @apply) */
<Button variant="primary" size="lg" />
/* 3. Prettier para ordenar las clases */
prettier-plugin-tailwindcss
/* 4. Evitar clases duplicadas/conflictivas */
/* Malo: class="p-4 p-2" */
/* 5. Usar variantes en vez de CSS custom */
hover:bg-blue-700 (no .btn:hover { })
/* 6. max-w-prose para texto largo */
<article class="max-w-prose">
/* 7. gap en vez de space-x/y */
class="flex gap-4"Buenas prácticas: 1) Siempre mobile-first (base → breakpoints mayores). 2) Extrae componentes en el framework (React/Vue/Blade) en vez de @apply. 3) Usa prettier-plugin-tailwindcss para un orden consistente. 4) Evita las clases duplicadas/conflictivas. 5) Prefiere variantes (hover:) al CSS custom. 6) max-w-prose para la legibilidad. 7) gap en vez de space-*.
Animaciones custom (@keyframes)
/* v4 (CSS): */
@theme {
--animate-fade-in: fade-in 0.3s ease-out;
--animate-slide-up: slide-up 0.5s ease-out;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from { opacity: 0; transform: translateY(1rem); }
to { opacity: 1; transform: translateY(0); }
}
/* Uso: class="animate-fade-in" */
/* v3 (config): */
theme: { extend: { animation: {
'fade-in': 'fade-in 0.3s ease-out' },
keyframes: { 'fade-in': { ... } } } }Animaciones custom: define @keyframes + una variable --animate-* (v4) o theme.extend.animation + keyframes (v3). Uso: animate-fade-in, animate-slide-up. Funciona con variantes: hover:animate-fade-in. Para animaciones complejas (stagger, spring), usa librerías como framer-motion o @tailwindcss/animate.
CVA (Class Variance Authority)
import { cva } from 'class-variance-authority'
const button = cva(
'px-4 py-2 rounded-lg font-medium transition',
{
variants: {
variant: {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
outline: 'border-2 border-blue-600 text-blue-600',
ghost: 'hover:bg-gray-100',
},
size: {
sm: 'px-3 py-1.5 text-sm',
lg: 'px-6 py-3 text-lg',
},
},
defaultVariants: { variant: 'primary', size: 'sm' },
}
)
<button class={button({ variant: 'outline', size: 'lg' })}>CVA (class-variance-authority) gestiona las variantes de clases en componentes React. Define clases base + variantes (variant, size) + defaults. Genera las clases correctas sin conflictos. Popular en React + Tailwind (shadcn/ui usa CVA). Alternativa: clsx + tailwind-merge para composición manual. Esencial para design systems con múltiples variantes.
sr-only y accesibilidad
/* Texto visible solo para lectores de pantalla: */ <a href="#contenido" class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:z-50 focus:px-4 focus:py-2 focus:bg-white focus:rounded-lg focus:shadow"> Saltar para o contenido </a> /* sr-only: */ /* position: absolute; width: 1px; height: 1px; */ /* padding: 0; margin: -1px; overflow: hidden; */ /* clip: rect(0,0,0,0); border: 0; */ /* Label accesible (sin visual): */ <label class="sr-only" for="búsqueda">Buscar</label> <input id="búsqueda" class="...">
sr-only oculta visualmente pero lo mantiene accesible a los lectores de pantalla (position absolute, 1px, clip). Esencial para: labels de inputs con icono, "skip links" (sr-only focus:not-sr-only = visible solo al enfocar con el teclado), texto descriptivo. focus:not-sr-only lo hace visible al enfocar (skip navigation). NUNCA uses hidden o display: none para contenido accesible.
Flexbox
Activar flex y dirección
<div class="flex">Contentor flex (linea horizontal)</div> <div class="inline-flex">Flex com display inline</div> /* Dirección: */ flex-row /* → horizontal (por defecto) */ flex-row-reverse /* ← horizontal invertido */ flex-col /* ↓ vertical (columna) */ flex-col-reverse /* ↑ vertical invertido */ /* Patrón responsivo más usado: */ class="flex flex-col md:flex-row" /* Apila en mobile, lado a lado en md+ */
flex convierte el elemento en un flex container — los hijos quedan lado a lado por defecto. flex-row (por defecto) = línea horizontal; flex-col = columna vertical. El patrón mobile-first más usado: flex-col md:flex-row = apila en mobile, lado a lado en md+. inline-flex = flex con display inline (para botones con icono).
flex-wrap
flex-wrap /* permite salto de línea */ flex-nowrap /* no salta (por defecto) */ flex-wrap-reverse /* salto invertido */ /* Lista de tags/chips: */ <div class="flex flex-wrap gap-2"> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 1</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 2</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 3</span> <span class="px-3 py-1 bg-gray-100 rounded-full text-sm">Tag 4</span> </div> /* Sin wrap: los items encogen o desbordan */
flex-wrap permite que los items pasen a la línea siguiente cuando no caben en horizontal. flex-nowrap (por defecto) fuerza todo en una línea (los items pueden encoger o desbordar). Esencial para listas de tags, chips, filtros, botones de toolbar. Combina con gap-2 para un espaciado consistente entre items en todas las líneas.
align-content (multi-línea)
/* Requiere flex-wrap + una altura definida para tener efecto */ content-start content-center content-between content-around content-evenly content-stretch /* por defecto */ <div class="flex flex-wrap content-center h-64 gap-4"> <div class="w-1/3 p-4 bg-gray-100">A</div> <div class="w-1/3 p-4 bg-gray-100">B</div> <div class="w-1/3 p-4 bg-gray-100">C</div> <div class="w-1/3 p-4 bg-gray-100">D</div> </div>
content-* alinea las LÍNEAS cuando hay flex-wrap y múltiples líneas. Sin wrap o con una sola línea, no tiene efecto. content-center = líneas centradas verticalmente en el contenedor. content-between = primera línea arriba, última abajo. Útil para grids de cards con altura fija donde quieres distribuir las líneas uniformemente.
Navbar con flex
<nav class="flex items-center justify-between px-6 h-16">
<!-- Logo -->
<a href="/" class="text-xl font-bold">Logo</a>
<!-- Links (centro) -->
<div class="hidden md:flex items-center gap-6">
<a href="#" class="text-gray-600 hover:text-gray-900">Inicio</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Sobre</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Contacto</a>
</div>
<!-- Acciones (derecha) -->
<div class="flex items-center gap-3">
<button class="px-4 py-2 text-sm">Entrar</button>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg text-sm">Registrar</button>
</div>
</nav>Navbar con flex: flex items-center justify-between distribuye el logo, los links y las acciones. h-16 para una altura consistente. Links con hidden md:flex (ocultos en mobile). gap-6 espacia los links. gap-3 para los botones de acción. Patrón de navegación universal — funciona en cualquier proyecto.
justify-content (eje principal)
justify-start /* inicio (por defecto) */ justify-end /* fin */ justify-center /* centro */ justify-between /* espacio ENTRE items */ justify-around /* espacio ALREDEDOR de cada item */ justify-evenly /* espacio IGUAL entre todos */ justify-stretch /* estirar para rellenar */ /* Navbar: logo a la izquierda, menu a la derecha */ <div class="flex justify-between items-center"> <span>Logo</span> <nav>Menu</nav> </div> /* Centrar horizontalmente: */ <div class="flex justify-center">...</div>
justify-* distribuye los items en el eje principal (horizontal en flex-row, vertical en flex-col). justify-between = primer item al inicio, último al final, espacio entre los demás. justify-center = todo centrado. El patrón más usado en navbars: justify-between items-center (logo + menu en los extremos, centrados verticalmente).
gap (espacio entre items)
gap-0, gap-1, gap-2, gap-3, gap-4, gap-6, gap-8 gap-x-4 /* solo horizontal (entre columnas) */ gap-y-2 /* solo vertical (entre filas) */ <div class="flex gap-4"> <div>Item</div> <div>Item</div> </div> <div class="grid grid-cols-3 gap-x-6 gap-y-4"> <div>Célula</div> </div> /* Responsivo: */ class="gap-2 md:gap-6"
gap-* define el espaciado entre flex/grid items — reemplaza los márgenes manuales. gap-x-* = horizontal, gap-y-* = vertical. Más limpio que space-x-*/space-y-* (que usan selectores complejos). Funciona en flex Y grid. Acepta prefijos responsivos: gap-2 md:gap-6 (más espacio en desktop). Es la forma moderna de espaciar items.
order (orden visual)
order-1, order-2, order-3 ... order-12 order-first /* order: -9999 */ order-last /* order: 9999 */ order-none /* order: 0 (por defecto) */ <div class="flex"> <div class="order-2">Visualmente 2º</div> <div class="order-1">Visualmente 1º</div> </div> /* Responsivo: imagen antes del texto en desktop */ <div class="flex flex-col md:flex-row"> <div class="order-2 md:order-1">Texto</div> <div class="order-1 md:order-2">Imagen</div> </div>
order-* reordena visualmente sin cambiar el HTML (el DOM mantiene el orden original). order-first = primero; order-last = último. Útil para responsivo: order-1 md:order-2 cambia el orden en md+. El valor por defecto es order-0. No afecta la accesibilidad (los lectores de pantalla siguen el orden del DOM, no el visual).
Media object (imagen + texto)
/* Comentario / perfil / notificación */
<div class="flex gap-4">
<img class="shrink-0 size-12 rounded-full object-cover"
src="avatar.jpg" alt="Avatar">
<div class="min-w-0">
<p class="font-semibold truncate">John Silva</p>
<p class="text-sm text-gray-600">Comentario aqui...</p>
<time class="text-xs text-gray-400">hace 2 horas</time>
</div>
</div>
/* min-w-0 permite truncate en el texto */El patrón "media object" (imagen + texto al lado): flex gap-4 + imagen con shrink-0 (no encoge) + contenido con min-w-0 (permite truncate). size-12 rounded-full para un avatar circular. min-w-0 es ESENCIAL en flex para permitir que el texto se trunque — sin él, el contenido nunca encoge por debajo de su tamaño natural.
align-items (eje cruzado)
items-start /* arriba */ items-end /* abajo */ items-center /* centro vertical */ items-baseline /* línea de base del texto */ items-stretch /* estirar (por defecto) */ /* Centrar verticalmente: */ <div class="flex items-center h-20"> <div>Centrado verticalmente</div> </div> /* Baseline (labels + inputs alineados): */ <div class="flex items-baseline gap-2"> <label>Nombre:</label> <input class="text-lg"> </div>
items-* alinea los items en el eje cruzado (vertical en flex-row). items-center = centrado verticalmente (el más usado). items-stretch (por defecto) = todos con la misma altura del más alto. items-baseline = alinea por la línea de base del texto (útil para labels + inputs de tamaños diferentes). items-start/items-end para arriba/abajo.
flex-grow y flex-shrink
grow /* flex-grow: 1 (crece para rellenar) */ grow-0 /* flex-grow: 0 (no crece) */ shrink /* flex-shrink: 1 (encoge si es necesario) */ shrink-0 /* flex-shrink: 0 (no encoge) */ /* Input + botón (patrón clásico): */ <div class="flex gap-2"> <input class="grow" placeholder="Buscar..."> <button class="shrink-0 px-4">Buscar</button> </div> /* Imagen fija + texto flexible: */ <div class="flex gap-4"> <img class="shrink-0 size-16" src="avatar.jpg"> <p class="grow">Texto que pode ser largo...</p> </div>
grow = crece para rellenar el espacio disponible. shrink-0 = no encoge (botones, labels, imágenes de tamaño fijo). Patrón clásico: input con grow + botón con shrink-0 (el input ocupa todo el espacio, el botón mantiene su tamaño). Sin shrink-0, el botón puede encoger y el texto saltar de línea.
Centrar a la perfección
/* Flexbox (más común): */
<div class="flex items-center justify-center h-screen">
<div class="text-center">
Centrado nos 2 eixos
</div>
</div>
/* Grid (una línea): */
<div class="grid place-items-center h-screen">
<div>Centrado</div>
</div>
/* Absolute + translate: */
<div class="relative h-64">
<div class="absolute top-1/2 left-1/2
-translate-x-1/2 -translate-y-1/2">
Centrado
</div>
</div>Tres formas de centrar: 1) flex items-center justify-center — la más usada, necesita una altura en el padre (h-screen, h-full). 2) grid place-items-center — una línea, más conciso. 3) absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 — para overlays y modales. El patrón moderno reemplaza los viejos hacks de margin: auto y transforms.
align-self (un item)
self-auto /* hereda del padre (por defecto) */ self-start /* arriba */ self-center /* centro */ self-end /* abajo */ self-stretch /* estirar */ self-baseline /* línea de base */ /* Botón al fondo de un card: */ <div class="flex flex-col h-full"> <h3>Título</h3> <p class="flex-1">Descripcion...</p> <button class="self-end mt-auto">Comprar</button> </div>
self-* sobrescribe el items-* del padre en un único item. Mismos valores: start, center, end, stretch, baseline. Útil cuando un item necesita una alineación distinta de sus hermanos. Ejemplo clásico: un botón al fondo de un card con self-end mt-auto (lo empuja hacia abajo independientemente del contenido de arriba).
flex (shorthand)
flex-1 /* flex: 1 1 0% (crece igual) */ flex-auto /* flex: 1 1 auto (base en el contenido) */ flex-initial /* flex: 0 1 auto (por defecto) */ flex-none /* flex: none (no crece/encoge) */ /* Columnas iguales: */ <div class="flex gap-4"> <div class="flex-1">A (1/3)</div> <div class="flex-1">B (1/3)</div> <div class="flex-1">C (1/3)</div> </div> /* Sidebar fija + contenido flexible: */ <div class="flex"> <aside class="flex-none w-64">Sidebar</aside> <main class="flex-1">Contenido</main> </div>
flex-1 = todos crecen igualmente (columnas de igual ancho). flex-auto = crece según el tamaño del contenido. flex-none = tamaño fijo (no flexible). flex-initial = por defecto (encoge pero no crece). Usa flex-1 para dividir el espacio en partes iguales. flex-none + flex-1 = sidebar fija + contenido que rellena el resto.
space-between (legacy)
/* space-x/y añade margen entre hijos (excepto el 1º) */ space-x-4 /* margin-left en los hijos (excepto el 1º) */ space-y-2 /* margin-top en los hijos (excepto el 1º) */ space-x-reverse /* HOY: prefiere gap */ <div class="flex gap-4"> ← moderno, simple <div class="flex space-x-4"> ← legacy, selectores complejos /* space-y sigue siendo útil para stacks verticales simples: */ <div class="space-y-4"> <p>Párrafo 1</p> <p>Párrafo 2</p> </div>
space-x-*/space-y-* añaden margen entre los hijos (excepto el primero) usando selectores > * + *. Hoy, gap-* es preferible: más simple, funciona en grid, sin selectores complejos. space-y-* sigue siendo conveniente para stacks verticales simples (párrafos, listas). En código nuevo, usa siempre gap.
Grid
Grid básico
<div class="grid grid-cols-3 gap-4"> <div class="bg-gray-100 p-4">1</div> <div class="bg-gray-100 p-4">2</div> <div class="bg-gray-100 p-4">3</div> <div class="bg-gray-100 p-4">4</div> </div> /* Patrón responsivo (cards): */ class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" /* 1 col mobile → 2 en sm → 3 en lg → 4 en xl */
grid + grid-cols-* define el numero de columnas. gap-4 espacia las celdas. El patrón responsivo para cards: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 = 1 columna en mobile, 2 en tablet, 3 en desktop, 4 en pantalla grande. Más simple que flex para layouts en cuadrícula regular.
row-span (ocupar filas)
row-span-1, row-span-2 ... row-span-6 row-span-full /* todas las filas */ <div class="grid grid-cols-3 grid-rows-3 gap-4"> <div class="row-span-2 bg-blue-100 p-4">Ocupa 2 lineas</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> <div class="bg-gray-100 p-4">Normal</div> </div> /* Mosaico tipo dashboard: */ <div class="col-span-2 row-span-2">Widget grande</div>
row-span-* hace que un item ocupe múltiples filas. row-span-2 = 2 filas de alto. row-span-full = todas las filas. Útil para sidebars, imágenes grandes en mosaicos o widgets de dashboard. Combina con col-span para crear áreas rectangulares de cualquier tamaño en un grid.
Grid responsivo (patrones)
/* Cards responsivos: */ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> /* Sidebar + contenido: */ <div class="grid grid-cols-1 md:grid-cols-[250px_1fr] gap-8"> <aside>Sidebar</aside> <main>Contenido</main> </div> /* Auto-fit (sin breakpoints): */ <div class="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6"> /* Holy grail (header + 3 cols + footer): */ <div class="grid grid-rows-[auto_1fr_auto] h-screen"> <header>Encabezado</header> <div class="grid grid-cols-[200px_1fr_200px]">...</div> <footer>Pie de página</footer> </div>
Patrones esenciales: grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 para cards responsivos. grid-cols-[250px_1fr] para una sidebar fija + contenido flexible. repeat(auto-fit,minmax(280px,1fr)) = grid totalmente responsivo sin media queries. "Holy grail" = grid anidado con header/footer fijos y 3 columnas. Grid es ideal para layouts bidimensionales.
grid-cols (nº de columnas)
grid-cols-1, grid-cols-2, grid-cols-3 ... grid-cols-12 grid-cols-none /* elimina grid */ /* Template arbitrario: */ grid-cols-[200px_1fr] /* sidebar + contenido */ grid-cols-[1fr_2fr_1fr] /* 3 columnas proporcionales */ grid-cols-[repeat(auto-fit,minmax(250px,1fr))] /* auto */ /* Responsivo: */ class="grid-cols-2 md:grid-cols-3 lg:grid-cols-6" /* Los underscores reemplazan espacios en los corchetes */
grid-cols-1 a grid-cols-12 para columnas iguales. grid-cols-[200px_1fr] para un template custom (sidebar fija + contenido flexible). repeat(auto-fit,minmax(250px,1fr)) = grid responsivo SIN breakpoints (columnas automáticas basadas en el espacio disponible). Usa underscores en vez de espacios dentro de los corchetes.
col-start y col-end
col-start-1, col-start-2 ... col-start-13 col-end-1, col-end-2 ... col-end-13 col-auto /* Item de la columna 2 a la 4 (2 columnas de ancho): */ <div class="col-start-2 col-end-4">Centrado</div> /* Centrar contenido en un grid de 12: */ <div class="grid grid-cols-12"> <div class="col-start-3 col-span-8">Contenido centrado</div> </div> /* Layout asimétrico: */ <div class="col-start-1 col-span-7">Principal</div> <div class="col-start-9 col-span-4">Lateral</div>
col-start-* y col-end-* posicionan items en líneas específicas del grid. Las líneas se numeran de 1 a N+1 (un grid de 12 tiene líneas 1-13). col-start-2 col-end-4 = de la línea 2 a la 4. Útil para layouts asimétricos, centrar contenido (col-start-3 col-span-8 en un grid de 12) y crear espacios vacíos intencionales.
gap y espaciado
gap-0, gap-1, gap-2, gap-3, gap-4, gap-6, gap-8 gap-x-4 /* solo entre columnas (horizontal) */ gap-y-2 /* solo entre filas (vertical) */ <div class="grid grid-cols-3 gap-x-6 gap-y-4"> <div>A</div> <div>B</div> <div>C</div> </div> /* Responsivo: */ class="gap-2 md:gap-6" /* Sin gap (bordes pegados): */ class="grid grid-cols-3 divide-x divide-y"
gap-* define el espacio entre celdas del grid. gap-x-* = horizontal (entre columnas), gap-y-* = vertical (entre filas). Reemplaza el viejo hack de márgenes negativos. Acepta prefijos responsivos: gap-2 md:gap-6 (más espacio en desktop). Para grids sin gap pero con separadores, usa divide-x divide-y en las celdas.
grid-rows
grid-rows-1, grid-rows-2 ... grid-rows-6 grid-rows-none /* Template arbitrario: */ grid-rows-[auto_1fr_auto] grid-rows-[200px_minmax(100px,1fr)] /* Layout full-height (header + main + footer): */ <div class="grid grid-rows-[auto_1fr_auto] h-screen"> <header class="bg-gray-100 p-4">Encabezado</header> <main class="p-8 overflow-y-auto">Contenido (estica)</main> <footer class="bg-gray-100 p-4">Pie de página</footer> </div>
grid-rows-* define el numero de filas. grid-rows-[auto_1fr_auto] = layout clásico: header con altura automática, main que se estira (1fr), footer automático. 1fr = fracción del espacio disponible. Combina con h-screen para un layout full-height sin scroll en la página (el scroll queda solo en el main con overflow-y-auto).
place-items y place-content
/* Alinear items dentro de las celdas: */ place-items-center /* centro en ambos ejes */ place-items-start place-items-end place-items-stretch /* por defecto */ /* Alinear el grid entero en el container: */ place-content-center place-content-between place-content-around /* Centrado perfecto en grid: */ <div class="grid place-items-center h-64"> <div>Centrado na célula</div> </div> /* Icono centrado en una celda cuadrada: */ <div class="grid place-items-center size-12 bg-gray-100 rounded-lg"> <svg class="size-6">...</svg> </div>
place-items-* alinea el contenido dentro de cada celda (atajo para items-* + justify-items-*). place-content-* alinea el grid entero en el container. place-items-center = centrado perfecto en grid (una línea). Útil para iconos en celdas cuadradas, avatares en celdas de tabla, y cualquier centrado simple.
col-span (ocupar columnas)
col-span-1, col-span-2 ... col-span-12 col-span-full /* ocupa TODAS las columnas */ <div class="grid grid-cols-4 gap-4"> <div class="col-span-2 bg-blue-100 p-4">Ocupa 2 columnas</div> <div class="bg-gray-100 p-4">1 col</div> <div class="bg-gray-100 p-4">1 col</div> <div class="col-span-full bg-green-100 p-4">Linea entera</div> </div> /* Item destacado en un grid de cards: */ <div class="col-span-2 row-span-2">Highlight</div>
col-span-* hace que un item ocupe múltiples columnas. col-span-2 = 2 columnas de ancho. col-span-full = todas las columnas (fila entera — útil para headers, banners, separadores). El item "empuja" a los siguientes a la posición disponible. Combina con row-span para áreas rectangulares grandes (destacados en mosaicos).
auto-flow (densidad)
grid-flow-row /* rellena por filas (por defecto) */ grid-flow-col /* rellena por columnas */ grid-flow-dense /* rellena los huecos */ grid-flow-row-dense /* filas + denso */ grid-flow-col-dense /* columnas + denso */ /* Mosaico sin espacios vacíos: */ <div class="grid grid-cols-3 grid-flow-dense gap-4"> <div class="col-span-2">Largo</div> <div>Normal</div> <div>Normal</div> <div>Normal</div> <div>Normal</div> </div>
grid-flow-row (por defecto) rellena fila a fila. grid-flow-col rellena columna a columna. grid-flow-dense rellena los huecos dejados por items con col-span (reordena visualmente para no dejar espacios vacíos). Útil para mosaicos tipo Pinterest, galerías de imágenes y dashboards con widgets de tamaños variados.
Formulários e Inputs
Input de texto
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Email
</label>
<input type="email"
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
transition-colors"
placeholder="nombre@ejemplo.com">
</div>Input completo: w-full px-3 py-2 (tamaño), rounded-lg border border-gray-300 (borde), shadow-sm (profundidad sutil), focus:ring-2 focus:ring-blue-500 (focus accesible), placeholder:text-gray-400 (placeholder sutil). Label con text-sm font-medium text-gray-700. transition-colors suaviza el cambio de estado.
Toggle switch
/* Toggle con peer (sin JS): */
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="peer sr-only">
<div class="w-11 h-6 bg-gray-300 rounded-full
peer-checked:bg-blue-600
peer-focus:ring-2 peer-focus:ring-blue-300
after:content-[''] after:absolute after:top-0.5
after:left-0.5 after:bg-white after:rounded-full
after:h-5 after:w-5 after:transition-all
peer-checked:after:translate-x-5
transition-colors"></div>
</label>
/* peer-checked: cambia el estilo cuando está marcado */Toggle switch sin JavaScript: peer sr-only en el checkbox (oculto pero accesible) + peer-checked:bg-blue-600 en el visual (cambia el color cuando está marcado). El "botón" usa after:content-[''] con after:translate-x-5 en checked para deslizar. sr-only mantiene el input accesible a los lectores de pantalla. transition-colors lo suaviza.
Input disabled y readonly
/* Disabled: */
<input disabled
class="w-full px-3 py-2 rounded-lg border border-gray-200
bg-gray-100 text-gray-500 cursor-not-allowed
placeholder:text-gray-400"
placeholder="Campo desativado">
/* Readonly: */
<input readonly
class="w-full px-3 py-2 rounded-lg border border-gray-200
bg-gray-50 text-gray-600 cursor-default"
value="No editável">
/* Estados vía la variante disabled: */
class="disabled:opacity-50 disabled:cursor-not-allowed
disabled:bg-gray-100"Disabled: bg-gray-100 text-gray-500 cursor-not-allowed (aspecto desactivado). Readonly: bg-gray-50 text-gray-600 cursor-default (aspecto ligeramente diferente). Usa la variante disabled: para estilizar estados: disabled:opacity-50 disabled:cursor-not-allowed. La diferencia: disabled no envía el valor; readonly lo envía pero no se puede editar.
Validación visual (peer)
/* Input con validación vía peer: */
<div>
<input type="email"
class="peer w-full px-3 py-2 rounded-lg border
border-gray-300
focus:ring-2 focus:ring-blue-500
invalid:border-red-500 invalid:ring-red-500"
required>
<p class="hidden peer-invalid:block mt-1
text-sm text-red-600">
Email inválido
</p>
<p class="hidden peer-valid:block mt-1
text-sm text-green-600">
✓ Email válido
</p>
</div>Validación visual con peer: invalid:border-red-500 en el input (borde rojo cuando es inválido). Mensajes: hidden peer-invalid:block (se muestra solo cuando es inválido) y hidden peer-valid:block (se muestra solo cuando es válido). Usa la validación nativa de HTML5 (required, type="email"). Sin JavaScript — el browser valida automáticamente.
Input con error
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Password
</label>
<input type="password"
class="w-full px-3 py-2 rounded-lg
border border-red-500 ring-1 ring-red-500
focus:outline-none focus:ring-2 focus:ring-red-500
placeholder:text-gray-400">
<p class="mt-1 text-sm text-red-600">
A password debe ter pelo menos 8 caracteres.
</p>
</div>
/* Éxito: border-green-500 + text-green-600 */Estado de error: border-red-500 ring-1 ring-red-500 (borde rojo con anillo). Mensaje: text-sm text-red-600 mt-1. Para éxito: border-green-500 + un mensaje text-green-600. El ring-1 refuerza la indicación visual. Asocia siempre el mensaje al input con aria-describedby para la accesibilidad.
Textarea
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Mensaje
</label>
<textarea rows="4"
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
resize-y transition-colors"
placeholder="Escribe a su mensaje..."></textarea>
<p class="mt-1 text-xs text-gray-500">Máx. 500 caracteres</p>
</div>Textarea: las mismas clases que el input + rows="4" (altura inicial) + resize-y (permite resize vertical, no horizontal). resize-none para desactivar el resize por completo. Texto de ayuda: text-xs text-gray-500 mt-1. Para textareas mayores, usa min-h-[120px]. El patrón de foco es idéntico al del input: focus:ring-2 focus:ring-blue-500.
File input
/* File input simple: */
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Fichero
</label>
<input type="file"
class="block w-full text-sm text-gray-500
file:mr-4 file:py-2 file:px-4
file:rounded-lg file:border-0
file:text-sm file:font-medium
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100
file:cursor-pointer cursor-pointer">
</div>
/* file: es la variante para el botón interno */File input estilizado: la variante file: estiliza el botón interno del input. file:py-2 file:px-4 file:rounded-lg (tamaño del botón), file:bg-blue-50 file:text-blue-700 (colores), hover:file:bg-blue-100 (hover). El texto del input: text-sm text-gray-500. file:border-0 quita el borde del botón. file:cursor-pointer para el cursor.
Select
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
País
</label>
<select
class="w-full px-3 py-2 rounded-lg
border border-gray-300 shadow-sm
bg-white text-gray-900
focus:outline-none focus:ring-2
focus:ring-blue-500 focus:border-blue-500
appearance-none
bg-[url('data:image/svg+xml,...')] bg-no-repeat
bg-[right_0.75rem_center] bg-[length:1rem]">
<option>Portugal</option>
<option>Brasil</option>
</select>
</div>Select estilizado: las mismas clases que el input + appearance-none (quita la flecha por defecto del browser) + un icono custom vía bg-[url(...)] posicionado con bg-[right_0.75rem_center]. bg-white garantiza un fondo consistente. Para una solución más simple, usa el plugin @tailwindcss/forms, que estiliza los selects automáticamente con un reset consistente.
Input group (prefijo/sufijo)
/* Con prefijo: */
<div class="flex">
<span class="inline-flex items-center px-3
rounded-l-lg border border-r-0 border-gray-300
bg-gray-50 text-gray-500 text-sm">
https://
</span>
<input class="flex-1 px-3 py-2 rounded-r-lg
border border-gray-300 focus:ring-2
focus:ring-blue-500 focus:border-blue-500"
placeholder="ejemplo.com">
</div>
/* Con un icono dentro: */
<div class="relative">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 size-5 text-gray-400">🔍</svg>
<input class="w-full pl-10 pr-4 py-2 rounded-lg border">
</div>Input group: prefijo con rounded-l-lg border-r-0 bg-gray-50 + input con rounded-r-lg flex-1 (bordes pegados). Para un icono dentro del input: relative en el padre + absolute left-3 top-1/2 -translate-y-1/2 en el icono + pl-10 en el input (padding para que no se solape con el icono). Patrón común en campos de búsqueda y URLs.
Plugin @tailwindcss/forms
/* Instalación: */
npm install -D @tailwindcss/forms
/* v3 (config): */
plugins: [require('@tailwindcss/forms')]
/* v4 (CSS): */
@plugin "@tailwindcss/forms";
/* El plugin aplica un reset consistente a: */
input, select, textarea, checkbox, radio
/* Antes: estilos inconsistentes entre browsers */
/* Después: base limpia y predecible */
/* Uso normal con clases Tailwind: */
<input class="rounded-lg border-gray-300
focus:ring-blue-500 focus:border-blue-500">El plugin @tailwindcss/forms aplica un reset consistente a todos los elementos de formulario (inputs, selects, textareas, checkboxes, radios). Quita los estilos inconsistentes entre browsers y proporciona una base limpia. Después, estiliza con clases Tailwind normales. Muy recomendado en cualquier proyecto con formularios. En v4, usa @plugin en el CSS.
Checkbox y radio
/* Checkbox custom: */
<label class="flex items-center gap-3 cursor-pointer">
<input type="checkbox"
class="size-4 rounded border-gray-300
text-blue-600 focus:ring-blue-500
focus:ring-offset-0 cursor-pointer">
<span class="text-sm text-gray-700">Aceito os termos</span>
</label>
/* Radio: */
<label class="flex items-center gap-3 cursor-pointer">
<input type="radio" name="opción"
class="size-4 border-gray-300
text-blue-600 focus:ring-blue-500 cursor-pointer">
<span class="text-sm text-gray-700">Opción A</span>
</label>Checkbox/radio con Tailwind: size-4 (tamaño), rounded (checkbox) o sin rounded (radio), border-gray-300 (borde), text-blue-600 (color cuando está marcado), focus:ring-blue-500 (focus). cursor-pointer en el label para indicar que es clicable. El plugin @tailwindcss/forms mejora el reset. gap-3 espacia el input del texto.
Formulario completo
<form class="space-y-6 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Nombre</label>
<input class="w-full px-3 py-2 rounded-lg border border-gray-300
focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input type="email" class="w-full px-3 py-2 rounded-lg border
border-gray-300 focus:ring-2 focus:ring-blue-500">
</div>
<div class="flex items-center gap-2">
<input type="checkbox" class="size-4 rounded text-blue-600">
<label class="text-sm text-gray-600">Lembrar-me</label>
</div>
<button class="w-full py-2.5 bg-blue-600 text-white rounded-lg
font-medium hover:bg-blue-700 transition-colors">
Entrar
</button>
</form>Formulario completo: space-y-6 espacia los campos. Cada campo: label (text-sm font-medium) + input (w-full px-3 py-2 rounded-lg border). Checkbox con flex items-center gap-2. Botón full-width: w-full py-2.5 bg-blue-600 rounded-lg font-medium. max-w-md limita el ancho para la legibilidad. Patrón universal de formularios.
Label flotante
/* Label que sube al enfocar (con peer): */
<div class="relative">
<input type="text" id="nombre" placeholder=" "
class="peer w-full px-3 pt-5 pb-2 rounded-lg
border border-gray-300
focus:ring-2 focus:ring-blue-500">
<label for="nombre"
class="absolute left-3 top-3.5 text-gray-500
transition-all duration-200
peer-focus:top-1.5 peer-focus:text-xs
peer-focus:text-blue-600
peer-[:not(:placeholder-shown)]:top-1.5
peer-[:not(:placeholder-shown)]:text-xs">
Nombre
</label>
</div>Label flotante: peer en el input + peer-focus:top-1.5 peer-focus:text-xs en el label (sube y encoge al enfocar). peer-[:not(:placeholder-shown)]: mantiene el label arriba cuando hay contenido. placeholder=" " (un espacio) es necesario para que el selector funcione. pt-5 pb-2 da espacio para el label. transition-all suaviza la animación.
Componentes Práticos
Botón reutilizable
<button class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-blue-600 text-white font-medium hover:bg-blue-700 active:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none transition-colors duration-200"> <svg class="size-5">...</svg> Clic aqui </button> /* Variantes: outline, ghost, danger */ class="border-2 border-blue-600 text-blue-600 hover:bg-blue-50" /* outline */
Botón completo: inline-flex items-center gap-2 (icono + texto alineados), px-5 py-2.5 (padding), rounded-lg (esquinas), estados hover/active/focus/disabled, transition-colors (suave). focus:ring-offset-2 para accesibilidad visible. Variantes: outline (border-2), ghost (hover:bg-gray-100), danger (bg-red-600).
Skeleton loading
<div class="animate-pulse space-y-4">
<div class="h-48 bg-gray-200 rounded-lg"></div>
<div class="space-y-2">
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
<div class="h-4 bg-gray-200 rounded w-5/6"></div>
</div>
<div class="flex gap-3">
<div class="size-10 bg-gray-200 rounded-full"></div>
<div class="h-4 bg-gray-200 rounded w-24 self-center"></div>
</div>
</div>Skeleton: animate-pulse + bloques bg-gray-200 rounded con alturas/anchos variados. h-4 w-3/4 simula líneas de texto. size-10 rounded-full simula un avatar. space-y-* espacia los bloques. Reemplaza con el contenido real cuando cargue (vía JS/framework). Patrón esencial de UX de loading — muestra la estructura mientras los datos aún no llegan.
Alert / Toast
/* Alert (inline): */ <div class="flex items-center gap-3 p-4 rounded-lg bg-green-50 border border-green-200"> <svg class="size-5 text-green-600 shrink-0">✓</svg> <p class="text-sm text-green-800">Operación realizada!</p> </div> /* Toast (fijo en la esquina): */ <div class="fixed bottom-4 right-4 z-50 flex items-center gap-3 px-4 py-3 bg-gray-900 text-white rounded-lg shadow-xl animate-in slide-in-from-bottom"> <span>Mensaje guardada</span> <button class="text-gray-400 hover:text-white">×</button> </div>
Alert inline: flex items-center gap-3 p-4 rounded-lg + colores semánticos (bg-green-50 border-green-200). Icono con shrink-0 (no se encoge). Toast: fixed bottom-4 right-4 z-50 (esquina inferior derecha), bg-gray-900 text-white shadow-xl (oscuro, destacado). Botón de cerrar: text-gray-400 hover:text-white. Usa animate-in para una entrada suave.
Avatar group
/* Grupo de avatares superpuestos: */
<div class="flex -space-x-3">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a1.jpg">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a2.jpg">
<img class="size-10 rounded-full ring-2 ring-white
object-cover" src="a3.jpg">
<span class="size-10 rounded-full ring-2 ring-white
bg-gray-200 flex items-center justify-center
text-xs font-medium text-gray-600">
+5
</span>
</div>
/* -space-x-3 superpone; ring-2 ring-white separa */Avatar group: flex -space-x-3 superpone los avatares (margen negativo). ring-2 ring-white crea una separación blanca entre ellos. size-10 rounded-full object-cover para avatares circulares uniformes. Contador: bg-gray-200 flex items-center justify-center text-xs (círculo gris con "+5"). Popular en listas de miembros, comentarios y actividad de equipo.
Card con hover
<div class="group max-w-sm rounded-xl overflow-hidden
bg-white shadow-md hover:shadow-xl
transition-shadow duration-300">
<div class="overflow-hidden">
<img src="foto.jpg" alt=""
class="w-full h-48 object-cover
group-hover:scale-105 transition-transform duration-300">
</div>
<div class="p-6">
<h3 class="font-semibold text-lg
group-hover:text-blue-600 transition-colors">
Título
</h3>
<p class="mt-2 text-gray-600 text-sm">Descripcion...</p>
</div>
</div>Card con efectos: hover:shadow-xl (elevación), group-hover:scale-105 (zoom en la imagen), group-hover:text-blue-600 (color en el título). overflow-hidden en el contenedor de la imagen + rounded-xl para esquinas redondeadas. transition-* lo suaviza todo. group propaga el hover del card a los hijos. Patrón esencial para listas de productos, blog posts y portfolios.
Modal / Dialog
<div class="fixed inset-0 z-50 flex items-center
justify-center p-4">
<!-- Overlay -->
<div class="absolute inset-0 bg-black/50
backdrop-blur-sm"></div>
<!-- Dialog -->
<div class="relative bg-white rounded-2xl shadow-xl
w-full max-w-md p-6 z-10">
<h2 class="text-lg font-semibold">Título</h2>
<p class="mt-2 text-gray-600">Contenido do modal...</p>
<div class="mt-6 flex justify-end gap-3">
<button class="px-4 py-2 text-gray-700
hover:bg-gray-100 rounded-lg">Cancelar</button>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg hover:bg-blue-700">Confirmar</button>
</div>
</div>
</div>Modal: fixed inset-0 z-50 (overlay a pantalla completa), bg-black/50 backdrop-blur-sm (fondo oscuro esmerilado), flex items-center justify-center (centra el dialog). Dialog: relative bg-white rounded-2xl shadow-xl max-w-md. z-10 por encima del overlay. Botones: flex justify-end gap-3. Usa el <dialog> nativo o Headless UI para accesibilidad completa.
Tabla responsiva
<div class="overflow-x-auto rounded-lg border border-gray-200">
<table class="w-full text-sm text-left">
<thead class="bg-gray-50 text-gray-600 uppercase text-xs">
<tr>
<th class="px-4 py-3 font-medium">Nombre</th>
<th class="px-4 py-3 font-medium">Email</th>
<th class="px-4 py-3 font-medium">Estado</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-4 py-3 font-medium">John</td>
<td class="px-4 py-3 text-gray-600">joao@mail.com</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-green-100 text-green-800
rounded-full text-xs">Activo</span>
</td>
</tr>
</tbody>
</table>
</div>Tabla: overflow-x-auto en el padre (scroll horizontal en mobile). w-full text-sm text-left en la tabla. Header: bg-gray-50 uppercase text-xs. Filas: divide-y divide-gray-200 (separadores). Hover: hover:bg-gray-50. Badge de estado con colores semánticos. px-4 py-3 para un padding consistente. Esencial para dashboards y listados.
Breadcrumb
<nav class="flex items-center gap-2 text-sm text-gray-500">
<a href="/" class="hover:text-gray-900 transition-colors">Inicio</a>
<span class="text-gray-300">/</span>
<a href="/productos" class="hover:text-gray-900">Productos</a>
<span class="text-gray-300">/</span>
<span class="text-gray-900 font-medium" aria-current="page">
Detalle
</span>
</nav>
/* Con icono de flecha: */
<svg class="size-4 text-gray-400">›</svg>
/* Separador con slash, flecha o icono */Breadcrumb: flex items-center gap-2 text-sm (línea horizontal). Links: text-gray-500 hover:text-gray-900 (gris, se oscurece al hacer hover). Página actual: text-gray-900 font-medium + aria-current="page" (accesibilidad). Separador: text-gray-300 (slash, flecha o icono). Esencial para la navegación jerárquica (e-commerce, documentación, dashboards).
Navbar responsiva
<nav class="sticky top-0 z-50 bg-white/80
backdrop-blur-md border-b border-gray-200">
<div class="container mx-auto px-4 h-16
flex items-center justify-between">
<a href="/" class="text-xl font-bold">Logo</a>
<div class="hidden md:flex items-center gap-6">
<a href="#" class="text-gray-600 hover:text-gray-900
transition-colors">Inicio</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Sobre</a>
<button class="px-4 py-2 bg-blue-600 text-white
rounded-lg text-sm font-medium hover:bg-blue-700">
Entrar
</button>
</div>
<button class="md:hidden text-2xl">☰</button>
</div>
</nav>Navbar moderna: sticky top-0 z-50 (fija al hacer scroll), bg-white/80 backdrop-blur-md (vidrio esmerilado), flex items-center justify-between (logo + menú en los extremos). Links hidden md:flex (desktop), botón md:hidden (mobile). h-16 para una altura consistente. container mx-auto px-4 limita el ancho. Patrón universal de navegación.
Dropdown menu
<div class="relative inline-block">
<button class="px-4 py-2 border rounded-lg">Opciones ▼</button>
<!-- Menú (oculto por defecto, mostrar vía JS) -->
<div class="absolute right-0 mt-2 w-48
bg-white rounded-lg shadow-lg border border-gray-200
py-1 z-10">
<a href="#" class="block px-4 py-2 text-sm text-gray-700
hover:bg-gray-100 transition-colors">Perfil</a>
<a href="#" class="block px-4 py-2 text-sm text-gray-700
hover:bg-gray-100">Ajustes</a>
<hr class="my-1 border-gray-200">
<a href="#" class="block px-4 py-2 text-sm text-red-600
hover:bg-red-50">Sair</a>
</div>
</div>Dropdown: relative en el padre + absolute right-0 mt-2 en el menú (posicionado debajo, alineado a la derecha). w-48 bg-white rounded-lg shadow-lg border (visual). Ítems: block px-4 py-2 text-sm hover:bg-gray-100. Separador: hr border-gray-200. Ítem peligroso: text-red-600 hover:bg-red-50. z-10 por encima del contenido. Muestra/oculta vía JS o data-[state=open]:block.
Hero section
<section class="relative bg-gradient-to-br from-blue-600
to-purple-700 text-white py-20 md:py-32">
<div class="container mx-auto px-4 text-center">
<h1 class="text-4xl md:text-6xl font-bold
leading-tight max-w-3xl mx-auto">
Construa algo increíble
</h1>
<p class="mt-6 text-lg md:text-xl text-blue-100
max-w-2xl mx-auto">
Descripcion do producto ou servicio em pocas palabras.
</p>
<div class="mt-10 flex flex-col sm:flex-row
gap-4 justify-center">
<a href="#" class="px-8 py-3 bg-white text-blue-700
rounded-lg font-semibold hover:bg-blue-50">Empezar</a>
<a href="#" class="px-8 py-3 border-2 border-white/50
rounded-lg font-semibold hover:bg-white/10">Saber mais</a>
</div>
</div>
</section>Hero section: bg-gradient-to-br from-blue-600 to-purple-700 (fondo con gradiente), py-20 md:py-32 (espacio vertical generoso). Título: text-4xl md:text-6xl font-bold max-w-3xl mx-auto (grande, centrado, limitado). Botones: flex flex-col sm:flex-row gap-4 justify-center (se apilan en mobile). CTA primario: fondo blanco; secundario: border-2 border-white/50.
Tabs / Separadores
<div class="border-b border-gray-200">
<nav class="flex gap-6 -mb-px">
<button class="pb-3 px-1 border-b-2 border-blue-600
text-blue-600 font-medium text-sm">
Activo
</button>
<button class="pb-3 px-1 border-b-2 border-transparent
text-gray-500 hover:text-gray-700
hover:border-gray-300 text-sm transition-colors">
Inactivo
</button>
</nav>
</div>
/* Contenido debajo: */
<div class="py-4">Contenido do tab activo</div>Tabs: border-b border-gray-200 en el contenedor (línea base). Tab activo: border-b-2 border-blue-600 text-blue-600 font-medium (subrayado azul). Inactivo: border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300. -mb-px superpone la línea base. pb-3 px-1 para el padding. Muestra/oculta el contenido vía JS o hidden.
Badge y tag
/* Badge simple: */ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800"> Activo </span> /* Con punto de estado: */ <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm bg-blue-50 text-blue-700"> <span class="size-2 rounded-full bg-blue-500"></span> Online </span> /* Removible (con hover): */ <span class="group inline-flex items-center gap-1 px-3 py-1 rounded-full bg-gray-100 text-sm"> Tag <button class="group-hover:text-red-600">×</button> </span>
Badge: inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium + colores semánticos (bg-green-100 text-green-800). Punto de estado: size-2 rounded-full bg-blue-500. Colores sutiles (fondo 50/100, texto 700/800) para un contraste legible sin ser agresivo. Removible: group + group-hover:text-red-600 en el botón ×.
Tooltip
/* Tooltip con group (solo CSS): */
<div class="relative group inline-block">
<button class="px-4 py-2 bg-gray-100 rounded-lg">
Hover aqui
</button>
<div class="absolute bottom-full left-1/2 -translate-x-1/2
mb-2 px-3 py-1.5 bg-gray-900 text-white text-xs
rounded-lg opacity-0 group-hover:opacity-100
transition-opacity pointer-events-none
whitespace-nowrap">
Texto do tooltip
<div class="absolute top-full left-1/2 -translate-x-1/2
border-4 border-transparent border-t-gray-900"></div>
</div>
</div>Tooltip solo con CSS: group en el padre + opacity-0 group-hover:opacity-100 en el tooltip (aparece al hacer hover). Posición: absolute bottom-full left-1/2 -translate-x-1/2 mb-2 (arriba, centrado). pointer-events-none para no interferir con el ratón. Flecha: border-4 border-transparent border-t-gray-900. whitespace-nowrap impide el salto de línea. Para producción, usa Headless UI o Radix.
Footer
<footer class="bg-gray-900 text-gray-400 py-12">
<div class="container mx-auto px-4
grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<h3 class="text-white font-semibold mb-4">Logo</h3>
<p class="text-sm">Descripcion da empresa...</p>
</div>
<div>
<h4 class="text-white font-medium mb-3 text-sm
uppercase tracking-wide">Producto</h4>
<ul class="space-y-2 text-sm">
<li><a href="#" class="hover:text-white transition-colors">Funcionalidades</a></li>
<li><a href="#" class="hover:text-white">Precios</a></li>
</ul>
</div>
</div>
<div class="container mx-auto px-4 mt-8 pt-8
border-t border-gray-800 text-sm text-center">
© 2024 Empresa
</div>
</footer>Footer: bg-gray-900 text-gray-400 py-12 (fondo oscuro). Grid de columnas: grid-cols-1 md:grid-cols-4 gap-8. Títulos: text-white font-medium uppercase tracking-wide text-sm. Links: hover:text-white transition-colors. Separador: border-t border-gray-800 mt-8 pt-8. Copyright centrado. Patrón universal de pie de página con múltiples columnas de links.
Progress bar
/* Barra de progreso: */
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div class="bg-blue-600 h-2.5 rounded-full transition-all
duration-500" style="width: 65%"></div>
</div>
/* Con label: */
<div class="flex justify-between text-sm mb-1">
<span class="font-medium text-gray-700">Progresso</span>
<span class="text-gray-500">65%</span>
</div>
/* Step progress: */
<div class="flex items-center gap-2">
<div class="size-8 rounded-full bg-blue-600 text-white
flex items-center justify-center text-sm">1</div>
<div class="flex-1 h-1 bg-blue-600"></div>
<div class="size-8 rounded-full bg-gray-200 text-gray-500
flex items-center justify-center text-sm">2</div>
</div>Progress bar: w-full bg-gray-200 rounded-full h-2.5 (track) + bg-blue-600 h-2.5 rounded-full (relleno con style="width: 65%"). transition-all duration-500 anima el cambio. Label: flex justify-between text-sm. Step progress: círculos numerados (size-8 rounded-full) + líneas conectoras (flex-1 h-1). Esencial para wizards y uploads.