DevTools

Cheatsheet Tailwind CSS

Framework CSS utility-first

Volver a los lenguajes
Tailwind CSS
154 tarjetas encontradas
Categorías:
Versiones:

Instalação e Configuração


14 cards
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-marcabg-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


14 cards
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


12 cards
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


14 cards
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


12 cards
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


12 cards
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


13 cards
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


10 cards
@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


14 cards
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


10 cards
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


13 cards
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


16 cards
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.