Tema
Tailwind CSS
Tailwind CSS es el framework de CSS más popular del momento. En lugar de escribir CSS en un archivo aparte, aplicas pequeñas clases utilitarias directamente en el HTML: p-4, flex, text-xl, bg-violet-600. Al principio parece extraño, pero muchos equipos lo adoptan porque permite construir interfaces muy rápido y mantener un diseño consistente. En esta lección aprenderás a instalar Tailwind v4, sus utilidades clave, responsive, estados, modo oscuro y personalización.
Concepto: utility-first
En el CSS "tradicional" (como con BEM) inventas un nombre para cada componente y escribes sus estilos en otro archivo. En Tailwind cada clase hace una sola cosa, y combinas muchas:
html
<button class="boton-primario">Comprar</button>
<style>
.boton-primario {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
background: #7c3aed;
color: #fff;
font-weight: 600;
}
.boton-primario:hover { background: #6d28d9; }
</style>html
<button class="px-4 py-2 rounded-lg bg-violet-600 text-white font-semibold hover:bg-violet-700">
Comprar
</button>Analogía
El CSS tradicional es como mandar a hacer un mueble a medida: cada pieza se diseña desde cero. Tailwind es como un juego de LEGO: piezas pequeñas y estandarizadas que combinas para armar lo que quieras, siempre con medidas que encajan entre sí.
Ventajas inmediatas:
- No inventas nombres ni saltas entre archivos HTML y CSS.
- Sistema de diseño incluido: espaciados, colores y tamaños vienen en una escala coherente (
p-1= 0.25rem,p-2= 0.5rem,p-4= 1rem...). - CSS final diminuto: Tailwind escanea tus archivos y sólo genera las clases que usas.
- Sin efectos secundarios: cambiar una clase en un botón no rompe otra página.
Instalación
Opción 1: CDN play (sólo para pruebas)
Para experimentar en un solo archivo HTML, sin instalar nada:
html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Tailwind v4 compilado en el navegador -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="bg-slate-100 p-8">
<h1 class="text-3xl font-bold text-violet-600">¡Hola, Tailwind!</h1>
</body>
</html>No lo uses en producción
El CDN compila las clases en el navegador del visitante cada vez que carga la página: es lento y pesado. Úsalo para prototipos, demos y aprender. Para un sitio real, usa Vite.
Opción 2: Tailwind v4 con Vite (la profesional)
Tailwind v4 simplificó muchísimo la instalación: ya no hay archivo tailwind.config.js obligatorio.
bash
npm create vite@latest mi-sitio -- --template vanilla
cd mi-sitio
npm install tailwindcss @tailwindcss/vitejs
// vite.config.js
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})css
/* src/style.css: ¡una sola línea! */
@import "tailwindcss";bash
npm run dev # servidor de desarrollo con recarga instantánea
npm run build # genera dist/ con el CSS mínimo y optimizadoInstala también la extensión Tailwind CSS IntelliSense de VS Code: autocompleta clases, muestra el CSS que genera cada una y avisa de conflictos.
Utilidades clave
No necesitas memorizarlas: con IntelliSense y la documentación las aprendes usando. Estas son las que más verás:
| Categoría | Ejemplos | Equivale a |
|---|---|---|
| Espaciado | p-4, px-6, mt-2, mx-auto, gap-4 | padding: 1rem, margin-inline: auto... |
| Tamaño | w-full, max-w-md, h-screen, size-12 | width: 100%, max-width: 28rem... |
| Layout | flex, grid, grid-cols-3, items-center, justify-between | Flexbox y Grid |
| Tipografía | text-sm, text-2xl, font-bold, leading-relaxed, text-center | tamaño, peso, interlineado |
| Color | text-slate-700, bg-violet-600, border-gray-200 | paleta de 50 a 950 |
| Bordes | border, rounded-xl, rounded-full | border-radius... |
| Efectos | shadow-md, opacity-50, transition, duration-300 | sombras, transiciones |
| Posición | relative, absolute, sticky, top-0, z-10 | position |
Valores arbitrarios cuando la escala no alcanza (úsalos poco):
html
<div class="w-[340px] bg-[#0f766e] grid-cols-[200px_1fr]">...</div>Responsive: sm, md, lg
Tailwind es mobile-first (como aprendiste en Responsive design): una clase sin prefijo aplica a todos los tamaños; con prefijo, desde ese breakpoint hacia arriba.
| Prefijo | Desde | Equivale a |
|---|---|---|
sm: | 640px | @media (min-width: 40rem) |
md: | 768px | @media (min-width: 48rem) |
lg: | 1024px | @media (min-width: 64rem) |
xl: | 1280px | @media (min-width: 80rem) |
2xl: | 1536px | @media (min-width: 96rem) |
html
<!-- 1 columna en móvil, 2 en tablet, 3 en escritorio -->
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
<div class="rounded-xl bg-white p-6 shadow">Diseño</div>
<div class="rounded-xl bg-white p-6 shadow">Desarrollo</div>
<div class="rounded-xl bg-white p-6 shadow">SEO</div>
</div>
<!-- Texto más grande en pantallas grandes; menú oculto en móvil -->
<h1 class="text-3xl md:text-5xl">Título</h1>
<nav class="hidden md:flex">...</nav>Error común
sm: no significa "en móviles". Significa "de 640px en adelante". Para estilos de móvil, escribe la clase sin prefijo.
Estados: hover, focus, group-hover
Cualquier utilidad acepta un prefijo de estado:
html
<!-- hover, focus-visible y active -->
<a href="#" class="rounded-lg bg-violet-600 px-4 py-2 text-white transition
hover:bg-violet-700 focus-visible:outline-2 focus-visible:outline-offset-2
focus-visible:outline-violet-600 active:scale-95">
Contactar
</a>
<!-- Campos de formulario -->
<input class="rounded-lg border border-slate-300 px-3 py-2
focus:border-violet-500 focus:ring-4 focus:ring-violet-200
invalid:border-red-500 disabled:opacity-50" type="email">
<!-- group: el hijo reacciona al hover del padre -->
<a href="#" class="group block rounded-xl bg-white p-6 shadow hover:shadow-lg">
<h3 class="font-bold group-hover:text-violet-600">Branding</h3>
<span class="inline-block transition group-hover:translate-x-1">→</span>
</a>También existen first:, last:, odd:, peer-checked:, has-checked: (basado en :has()), motion-reduce: y muchos más.
Modo oscuro
Por defecto, dark: sigue la preferencia del sistema (prefers-color-scheme):
html
<div class="bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100">
<p class="text-slate-600 dark:text-slate-400">Se adapta solo al tema del sistema.</p>
</div>Si quieres un botón para alternar el tema manualmente, redefine la variante en tu CSS para que dependa de una clase en html:
css
@import "tailwindcss";
/* dark: se activa cuando <html> tiene la clase "dark" */
@custom-variant dark (&:where(.dark, .dark *));js
// Botón de tema
document.querySelector('#tema').addEventListener('click', () => {
document.documentElement.classList.toggle('dark')
})Personalización con @theme
En v4 la configuración vive en el CSS. @theme define design tokens que se convierten a la vez en utilidades y en variables CSS:
css
@import "tailwindcss";
@theme {
/* Colores de marca → bg-marca-500, text-marca-700... */
--color-marca-50: #f5f3ff;
--color-marca-500: #7c3aed;
--color-marca-700: #5b21b6;
/* Tipografía → font-display */
--font-display: "Poppins", sans-serif;
/* Breakpoint extra → 3xl: */
--breakpoint-3xl: 1920px;
/* Radio → rounded-tarjeta */
--radius-tarjeta: 1.25rem;
}html
<h2 class="font-display text-marca-700">Estudio Nova</h2>
<div class="rounded-tarjeta bg-marca-50 p-6">...</div>Además, todas esas variables quedan disponibles en tu CSS: color: var(--color-marca-500);.
@apply con moderación
@apply permite agrupar utilidades dentro de una clase propia:
css
@import "tailwindcss";
@layer components {
.btn {
@apply inline-flex items-center gap-2 rounded-lg px-4 py-2 font-semibold transition;
}
.btn-primario {
@apply bg-marca-500 text-white hover:bg-marca-700;
}
}Buena práctica
Si usas @apply para todo, vuelves al CSS tradicional con un paso extra. La forma recomendada de reutilizar en Tailwind es crear componentes (en Vue, React, Astro, Blade, o un parcial de tu plantilla) que contienen las clases una sola vez. Reserva @apply para casos donde no controlas el HTML (contenido de un CMS) o para elementos muy repetidos como botones.
Ejemplos reales
Mira la tarjeta, la navbar y el hero funcionando (prueba los modos móvil y escritorio):
Tarjeta de producto
html
<article class="group max-w-sm overflow-hidden rounded-2xl bg-white shadow-md transition hover:-translate-y-1 hover:shadow-xl">
<img class="aspect-video w-full object-cover" src="img/curso.webp" alt="Curso de CSS">
<div class="flex flex-col gap-2 p-6">
<span class="self-start rounded-full bg-violet-100 px-3 py-1 text-xs font-bold text-violet-700">Nuevo</span>
<h3 class="text-lg font-bold text-slate-900 group-hover:text-violet-700">Curso de CSS</h3>
<p class="text-sm leading-relaxed text-slate-600">De cero a profesional con proyectos reales.</p>
<div class="mt-4 flex items-center justify-between">
<span class="text-2xl font-extrabold">$499</span>
<a href="#" class="rounded-lg bg-violet-600 px-4 py-2 text-sm font-semibold text-white hover:bg-violet-700">Comprar</a>
</div>
</div>
</article>Navbar responsive
html
<header class="sticky top-0 z-10 border-b border-slate-200 bg-white/80 backdrop-blur">
<nav class="mx-auto flex max-w-6xl items-center justify-between px-4 py-3">
<a href="/" class="text-xl font-extrabold text-violet-600">Nova</a>
<ul class="hidden gap-6 text-sm font-medium text-slate-700 md:flex">
<li><a class="hover:text-violet-600" href="#servicios">Servicios</a></li>
<li><a class="hover:text-violet-600" href="#proyectos">Proyectos</a></li>
<li><a class="hover:text-violet-600" href="#contacto">Contacto</a></li>
</ul>
<a href="#contacto" class="rounded-full bg-slate-900 px-4 py-2 text-sm text-white">Cotizar</a>
</nav>
</header>Hero
html
<!-- bg-linear-to-br: degradado lineal hacia abajo a la derecha (en v3 se llamaba bg-gradient-to-br) -->
<section class="bg-linear-to-br from-violet-600 to-indigo-700 px-4 py-20 text-center text-white">
<h1 class="mx-auto max-w-3xl text-4xl font-extrabold tracking-tight text-balance md:text-6xl">
Sitios web que convierten visitas en clientes
</h1>
<p class="mx-auto mt-6 max-w-xl text-lg text-violet-100">
Diseño, desarrollo y SEO para negocios que quieren crecer.
</p>
<div class="mt-8 flex flex-col justify-center gap-3 sm:flex-row">
<a href="#" class="rounded-full bg-white px-6 py-3 font-semibold text-violet-700 hover:bg-violet-50">Empezar</a>
<a href="#" class="rounded-full border border-white/40 px-6 py-3 font-semibold hover:bg-white/10">Ver portafolio</a>
</div>
</section>Ordena tus clases
Con muchas clases, el orden ayuda a leer. Instala el plugin oficial prettier-plugin-tailwindcss: ordena las clases automáticamente al guardar.
Pros y contras
| Pros | Contras |
|---|---|
| Desarrollo muy rápido, sin cambiar de archivo | HTML largo y "ruidoso" |
| Diseño consistente gracias a la escala | Curva inicial para aprender los nombres |
| CSS final muy pequeño | Sin componentes, se repiten muchas clases |
| No hay conflictos de nombres ni de cascada | Necesitas saber CSS de todos modos para entender qué hace cada clase |
| Gran comunidad y ecosistema (Tailwind UI, Flowbite, shadcn/ui) | Puede chocar con equipos acostumbrados a BEM |
¿Entonces aprendí CSS para nada?
¡Al contrario! Tailwind es sólo una forma rápida de escribir CSS. flex items-center justify-between sólo tiene sentido si entiendes Flexbox. Quien domina CSS aprende Tailwind en una tarde; quien sólo sabe Tailwind se atora en cuanto algo no sale.
Ejercicios
- Con el CDN, crea un botón con fondo esmeralda, texto blanco, esquinas redondeadas, que se oscurezca al pasar el mouse y tenga un anillo visible con el teclado.
- Crea una galería de 6 cuadros: 2 columnas en móvil, 3 en tablet (
md) y 6 en escritorio (lg). - Haz una tarjeta que en modo oscuro tenga fondo
slate-800y textoslate-100. - Define en
@themeun color--color-cliente-600: #0f766ey úsalo en un título.
Ver solución
html
<!-- 1 -->
<button class="rounded-lg bg-emerald-600 px-5 py-2.5 font-semibold text-white transition
hover:bg-emerald-700 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-emerald-300">
Enviar
</button>
<!-- 2 -->
<div class="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-6">
<div class="aspect-square rounded-lg bg-violet-200"></div>
<div class="aspect-square rounded-lg bg-violet-300"></div>
<div class="aspect-square rounded-lg bg-violet-400"></div>
<div class="aspect-square rounded-lg bg-violet-500"></div>
<div class="aspect-square rounded-lg bg-violet-600"></div>
<div class="aspect-square rounded-lg bg-violet-700"></div>
</div>
<!-- 3 -->
<article class="rounded-xl bg-white p-6 text-slate-900 shadow dark:bg-slate-800 dark:text-slate-100">
<h3 class="font-bold">Modo oscuro</h3>
<p class="text-slate-600 dark:text-slate-300">Cambia según el sistema.</p>
</article>css
/* 4 */
@import "tailwindcss";
@theme {
--color-cliente-600: #0f766e;
}html
<h2 class="text-3xl font-bold text-cliente-600">Clínica Dental Sonrisa</h2>Resumen
- Tailwind es utility-first: muchas clases pequeñas de una sola responsabilidad.
- Para probar: CDN
@tailwindcss/browser@4. Para proyectos: Vite +@tailwindcss/vite+@import "tailwindcss";. - Responsive mobile-first: sin prefijo = móvil;
sm:,md:,lg:= desde ese ancho. - Estados con prefijos:
hover:,focus-visible:,group-hover:,disabled:. dark:sigue al sistema o a una clase con@custom-variant.- Personaliza con
@theme; usa@applycon moderación y prefiere componentes. - Saber CSS sigue siendo indispensable para usar Tailwind bien.
Siguiente: Bootstrap.