Saltar al contenido
tailwind.css · devschool

Tailwind CSS

Lección 47 de 50 · 12 min de lectura · Actualizado el

En esta lección
  1. ¿Qué es el CSS de utilidades?
  2. Ventajas e inconvenientes
  3. Probarlo sin instalar nada
  4. Las clases básicas
  5. Responsive: sm:, md:, lg:
  6. Estados: hover:, focus: y más
  7. Modo oscuro: dark:
  8. Instalar Tailwind en un proyecto con Vite
  9. Personalizar el tema
  10. Tailwind frente a Bootstrap
  11. Errores frecuentes
  12. Resumen

Tailwind CSS es hoy uno de los frameworks de CSS más usados, sobre todo en proyectos con React, Vue o Astro. Su idea es muy distinta a la que has aprendido hasta ahora: en lugar de escribir reglas en un archivo .css, aplicas directamente en el HTML muchas clases pequeñas, cada una con una sola función. Al principio choca, pero entender por qué tantos equipos lo usan te ayudará en entrevistas y en proyectos reales. En esta lección verás qué es el CSS de utilidades, sus ventajas e inconvenientes, cómo probarlo sin instalar nada, sus clases básicas, el responsive, los estados, el modo oscuro, cómo instalarlo en un proyecto con Vite y cómo se compara con Bootstrap.

¿Qué es el CSS de utilidades?

Una clase de utilidad es una clase que hace una sola cosa: p-4 pone un relleno, text-center centra el texto, bg-white pone el fondo blanco. Compara las dos formas de hacer un botón:

Con CSS “tradicional”, inventas un nombre y escribes sus reglas aparte:

<button class="boton-reservar">Reservar</button>
.boton-reservar {
  padding: 8px 16px;
  background: #2563eb;
  color: white;
  font-weight: 600;
  border-radius: 8px;
}
.boton-reservar:hover {
  background: #1d4ed8;
}

Con Tailwind, todo va en el HTML y no escribes CSS:

<button class="rounded-lg bg-blue-600 px-4 py-2 font-semibold text-white hover:bg-blue-700">
  Reservar
</button>

Cada clase corresponde a una o dos declaraciones de CSS. A este enfoque se le llama utility-first (primero las utilidades).

Ventajas e inconvenientes

Ventajas:

  • No inventas nombres. Uno de los problemas más pesados de CSS es nombrar cosas (.tarjeta-producto-destacada-interior…). Aquí no hace falta.
  • No cambias de archivo. Ves el aspecto de cada elemento en el propio HTML.
  • Sin efectos colaterales. Cambiar las clases de un botón no rompe otro en otra página, porque no hay reglas compartidas que la cascada mezcle.
  • Diseño coherente. Los espaciados, colores y tamaños salen de una escala fija (p-2, p-4, p-6…), así que es difícil acabar con 30 tonos de gris distintos.
  • CSS final pequeño. Tailwind genera solo las clases que usas.

Inconvenientes:

  • HTML muy cargado. Un elemento puede llevar 15 clases y cuesta leerlo.
  • Repetición. Si tienes 20 botones iguales, repites las mismas clases 20 veces, salvo que uses componentes (en React, Astro…) o un bucle.
  • Hay que aprender sus nombres, y para eso necesitas saber CSS: justify-between solo tiene sentido si conoces Flexbox.
  • Necesita un paso de compilación en un proyecto real.

Nota: Tailwind no sustituye a saber CSS; lo da por supuesto. Cada clase es una propiedad que ya conoces con otro nombre. Por eso esta lección está al final del curso.

Probarlo sin instalar nada

Para experimentar, Tailwind ofrece un script que funciona directamente en el navegador (lo llaman Play CDN). Basta con añadirlo al <head>:

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Probando Tailwind</title>
  <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-blue-700">Hola, Tailwind</h1>
</body>
</html>

El script lee las clases de la página y genera el CSS al vuelo. Es perfecto para aprender y para prototipos, pero no lo uses en una web publicada: es lento y pesado. Para eso está la instalación con Vite que verás más abajo.

Las clases básicas

La escala de espaciado

Los espaciados usan números: cada unidad vale 0,25 rem (4 px con el tamaño de letra por defecto).

ClaseCSSTamaño
p-1padding: 0.25rem4 px
p-4padding: 1rem16 px
px-6padding-inline: 1.5rem24 px a izquierda y derecha
py-2padding-block: 0.5rem8 px arriba y abajo
mt-8margin-top: 2rem32 px arriba
mx-automargin-inline: autoCentrar un bloque
gap-4gap: 1rem16 px entre hijos

Las letras indican el lado: t (arriba), b (abajo), l (izquierda), r (derecha), x (horizontal), y (vertical). Lo mismo para tamaños: w-64 (ancho de 16 rem), w-full (100 %), max-w-md (ancho máximo medio), h-screen (alto de la pantalla).

Colores

Los colores tienen nombre y un tono del 50 (muy claro) al 950 (muy oscuro):

<p class="text-slate-700">Texto gris oscuro</p>
<div class="bg-emerald-100 text-emerald-800">Aviso verde suave</div>
<div class="border border-red-500">Borde rojo</div>

El prefijo indica dónde se aplica: text- (color del texto), bg- (fondo), border- (borde). Para la transparencia se añade una barra: bg-black/50 es negro al 50 %.

Tipografía

<h2 class="text-2xl font-bold tracking-tight">Horarios</h2>
<p class="text-sm leading-relaxed text-slate-600">Abierto de 7:00 a 22:00.</p>
<p class="text-center uppercase">Centrado y en mayúsculas</p>

Tamaños: text-xs, text-sm, text-base, text-lg, text-xl, text-2xl… Grosores: font-normal, font-semibold, font-bold.

Bordes, esquinas y sombras

border, border-2, rounded, rounded-lg, rounded-full (círculo o píldora), shadow, shadow-md, shadow-lg.

Flexbox y Grid

<!-- Barra: logo a la izquierda, enlaces a la derecha, alineados por el centro -->
<nav class="flex items-center justify-between gap-4 p-4">
  <a href="/" class="font-bold">Mi gimnasio</a>
  <div class="flex gap-4">
    <a href="/clases/">Clases</a>
    <a href="/tarifas/">Tarifas</a>
  </div>
</nav>

<!-- Rejilla de 3 columnas iguales -->
<div class="grid grid-cols-3 gap-6">
  <div>1</div> <div>2</div> <div>3</div>
</div>

<!-- Centrar en la pantalla -->
<main class="grid min-h-screen place-items-center">
  <p>En el centro</p>
</main>

Si conoces Flexbox, Grid y las recetas de centrar elementos, estas clases se leen solas: flex es display: flex, items-center es align-items: center, justify-between es justify-content: space-between.

Valores a medida

Si necesitas un valor que no está en la escala, ponlo entre corchetes:

<div class="w-[350px] bg-[#2d6cdf] top-[117px]">...</div>

Úsalo con moderación: si lo haces a menudo, pierdes la coherencia de la escala.

Responsive: sm:, md:, lg:

Tailwind es mobile first, como viste en responsive: una clase sin prefijo se aplica siempre, y una con prefijo se aplica a partir de ese ancho.

PrefijoA partir de
sm:640 px (40 rem)
md:768 px (48 rem)
lg:1024 px (64 rem)
xl:1280 px (80 rem)
2xl:1536 px (96 rem)
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
  ...
</div>

Se lee así: una columna en el móvil, dos desde 768 px y cuatro desde 1024 px. Equivale a escribir dos media queries con min-width.

<!-- Menú oculto en el móvil, visible desde md -->
<ul class="hidden md:flex md:gap-6">...</ul>

Cuidado: sm: no significa “en móviles”, sino “desde 640 px”. Para estilos de móvil, usa la clase sin prefijo.

Estados: hover:, focus: y más

Los prefijos de estado equivalen a las pseudoclases:

<a class="text-blue-700 underline hover:text-blue-900">Ver horarios</a>

<input class="rounded border border-slate-300 p-2 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-200">

<button class="bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800 disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2">
  Enviar
</button>

Fíjate en el campo: quita el outline con focus:outline-none, pero lo sustituye por un anillo (ring). Nunca quites el foco sin alternativa (lo tienes en CSS accesible).

Puedes combinar prefijos: md:hover:bg-blue-700 se aplica al pasar el ratón y solo desde 768 px. Y hay prefijos para relaciones: group-hover: (cuando el ratón pasa sobre un padre con la clase group) o first:, last:, odd: para los hijos de una lista.

Modo oscuro: dark:

El prefijo dark: aplica la clase cuando el usuario tiene el sistema en modo oscuro (por debajo usa prefers-color-scheme, que viste en modo oscuro):

<body class="bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100">
  <div class="rounded-lg bg-slate-100 p-4 dark:bg-slate-800">
    Tarjeta que se adapta al tema
  </div>
</body>

Si quieres un botón para que el usuario elija el tema, cambia el funcionamiento de dark: para que dependa de una clase o un atributo en <html>. En la versión 4 se hace en tu CSS:

@import "tailwindcss";

@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));

Ahora dark: se activa cuando <html data-theme="dark">, y tu JavaScript solo tiene que cambiar ese atributo.

Instalar Tailwind en un proyecto con Vite

Para una web real, Tailwind se integra en el proceso de construcción. Con Vite (la herramienta más usada para proyectos de JavaScript) y Tailwind v4 son pocos pasos. Necesitas Node.js.

  1. Crea un proyecto de Vite (elige la plantilla Vanilla si no usas ningún framework) e instala sus dependencias:
npm create vite@latest mi-web
cd mi-web
npm install
  1. Instala Tailwind y su complemento para Vite:
npm install tailwindcss @tailwindcss/vite
  1. Activa el complemento en vite.config.js (créalo en la raíz si no existe):
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [tailwindcss()],
});
  1. En tu archivo CSS principal (en la plantilla Vanilla, src/style.css), borra lo que haya y escribe:
@import "tailwindcss";
  1. Arranca el servidor de desarrollo:
npm run dev

Ya puedes usar las clases en tu index.html. Tailwind escanea tus archivos, detecta qué clases usas y genera solo esas. Cuando ejecutes npm run build, el CSS final ocupará unos pocos kilobytes.

Nota: en tutoriales y proyectos anteriores a 2025 verás Tailwind v3, que se configuraba con un archivo tailwind.config.js, las directivas @tailwind base; @tailwind components; @tailwind utilities; y PostCSS. La v4 ya no necesita nada de eso: todo se configura en el propio CSS.

Personalizar el tema

Tu marca tendrá sus propios colores y fuentes. En la v4 se definen con la regla @theme, usando variables CSS con nombres especiales:

@import "tailwindcss";

@theme {
  --color-marca: #e76f51;
  --color-marca-oscuro: #b4502f;
  --font-titulos: "Poppins", sans-serif;
  --breakpoint-3xl: 120rem;
}

Cada variable crea clases nuevas automáticamente:

VariableClases que genera
--color-marcabg-marca, text-marca, border-marca…
--font-titulosfont-titulos
--breakpoint-3xlEl prefijo 3xl:

Además, como son variables CSS de verdad, puedes usarlas en tu propio CSS con var(--color-marca).

@apply: cuando repites mucho

Si un conjunto de clases se repite en muchos sitios y no usas componentes, puedes agruparlas en una clase propia con @apply:

@layer components {
  .boton {
    @apply rounded-lg bg-marca px-4 py-2 font-semibold text-white hover:bg-marca-oscuro;
  }
}

No abuses: si acabas escribiendo todo con @apply, has vuelto al CSS tradicional con un paso extra. La forma recomendada de no repetir es crear componentes en tu framework (un Boton.astro, un Boton.jsx).

Tailwind frente a Bootstrap

Los dos son frameworks de CSS muy populares, pero con filosofías distintas:

TailwindBootstrap
EnfoqueUtilidades: tú construyes cada componenteComponentes ya hechos: .btn, .card, .navbar
AspectoNo tiene aspecto propio; cada web es distintaLas webs se parecen (“cara de Bootstrap”)
JavaScriptNo incluyeIncluye JS para menús, modales, carruseles
Velocidad para un prototipoMediaMuy alta
PersonalizaciónMuy fácil (@theme)Con variables de Sass o CSS
Tamaño del CSS finalSolo lo que usasGrande, salvo que lo recortes
InstalaciónNecesita compilar (salvo el Play CDN)Basta un <link>

¿Cuál elegir? Bootstrap es ideal para paneles de administración, prototipos rápidos y cuando quieres componentes listos. Tailwind encaja mejor en proyectos con un diseño propio y con un framework de componentes (React, Vue, Astro). En el mundo laboral encontrarás los dos, así que te conviene conocer la idea de ambos.

Errores frecuentes

  • Usar Tailwind sin saber CSS. Te pierdes en cuanto algo no sale como esperas. Aprende primero Flexbox, Grid y el modelo de caja.
  • Construir nombres de clase con variables, como `bg-${color}-500` en JavaScript. Tailwind busca clases completas en tus archivos; si la clase no aparece escrita tal cual, no la genera. Escribe las clases enteras (bg-red-500, bg-green-500).
  • Pensar que sm: es para móviles. Es “desde 640 px”. El móvil es la clase sin prefijo.
  • Usar el Play CDN en producción: lento y pesado.
  • Seguir un tutorial de v3 con la v4 (o al revés). Mira la versión antes de copiar la configuración.
  • Quitar el foco con outline-none sin poner un ring o un outline alternativo.
  • Abusar de @apply y de los valores entre corchetes, perdiendo las ventajas del sistema.

Resumen

ConceptoEjemploEquivale a
Espaciadop-4, mt-8, mx-auto, gap-4padding, margin, gap (1 unidad = 0,25 rem)
Colorbg-blue-600, text-slate-700, bg-black/50background, color
Tipografíatext-xl, font-bold, text-centerfont-size, font-weight, text-align
Flexboxflex items-center justify-betweendisplay: flex y alineación
Gridgrid grid-cols-3 gap-6display: grid y columnas
Responsivemd:grid-cols-2@media (min-width: 48rem)
Estadoshover:, focus-visible:, disabled:Pseudoclases
Modo oscurodark:bg-slate-900prefers-color-scheme: dark
Instalar@tailwindcss/vite + @import "tailwindcss";Paso de compilación
Tema@theme { --color-marca: ...; }Clases propias

Ahora que conoces el enfoque de utilidades, compáralo con el de componentes en la siguiente lección: Bootstrap.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

tailwind.html
Resultado

Pon a prueba lo que has aprendido

[CSS] En Tailwind, ¿qué significa md:grid-cols-2?

[CSS] ¿Por qué no funciona className={`bg-${color}-500`} con Tailwind?

[CSS] ¿Qué CSS genera p-4 (con la escala por defecto)?

[CSS] ¿Cuál es una ventaja de las clases de utilidad frente a CSS tradicional?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.