Lección 2 de 313 min
Frameworks CSS: Tailwind y Bootstrap
Dos filosofías opuestas: clases utilitarias que compones tú frente a componentes listos para usar.
Llevas un rato escribiendo CSS y notas que inventar nombres de clase (.tarjeta-producto-destacada__titulo) y saltar entre el HTML y la hoja de estilos te ocupa más tiempo que el diseño en sí. Los frameworks CSS atacan ese problema desde dos lados opuestos.
Tailwind CSS te da miles de clases pequeñas, cada una con una sola tarea, para que compongas el diseño directamente en el HTML. Bootstrap te da componentes ya diseñados (botones, barras de navegación, ventanas modales) que montas con unas pocas clases. Esta misma app está hecha con Tailwind v4, así que todo lo que ves en pantalla es un ejemplo de lo que vas a aprender.
Tailwind CSS: utilidades que compones tú
En Tailwind no escribes .tarjeta { padding: 1rem; }: escribes class="p-4". Cada clase es una utilidad, que hace una sola cosa y siempre la misma.
Tailwind CSS
Un framework de utilidades: clases pequeñas que combinas directamente en el HTML.
- Enfoque:
- utility-first
- Genera:
- solo las clases que usas
Tailwind es un framework utility-first: en lugar de componentes ya hechos, te da clases de una sola tarea, como p-4 (relleno), rounded-xl (esquinas), bg-white (fondo) o flex (distribución). El diseño sale de combinarlas, sin inventar nombres de clase ni cambiar de archivo.
Tailwind analiza tus archivos fuente (plantillas de Angular, componentes de React, HTML…) y genera solo el CSS de las clases que encuentra escritas. Por eso la hoja final suele ser pequeña, aunque existan miles de utilidades posibles.
Los valores salen de una escala común de espaciados, colores y tamaños de texto, de modo que el diseño queda coherente casi sin esfuerzo: es difícil que cada pantalla acabe con un gris distinto.
Úsalo cuando
Cuando construyes tu propio diseño y trabajas con componentes (Angular, React, Vue): si repites las mismas clases, creas un componente, no una clase CSS.
Ten en cuenta
Nunca construyas nombres de clase concatenando texto ('bg-' + color): Tailwind no los ve al analizar el código y no genera su CSS. Escribe las clases enteras y elige entre ellas.
<article class="flex items-center gap-4 rounded-xl bg-white p-4 shadow-md">
<img class="size-12 rounded-full" [src]="foto()" alt="" />
<div>
<h3 class="font-semibold text-zinc-900">{{ nombre() }}</h3>
<p class="text-sm text-zinc-500">{{ puesto() }}</p>
</div>
</article>Variantes y diseño responsive
Prefijos como hover:, md: o dark: aplican una utilidad solo en ciertas condiciones.
- Breakpoints:
- sm, md, lg, xl, 2xl
- md por defecto:
- 48rem (768px)
Una variante es un prefijo que condiciona la utilidad: hover:bg-sky-700 cambia el fondo al pasar el puntero, focus-visible:outline-2 dibuja el foco al navegar con el teclado y disabled:opacity-50 atenúa un botón desactivado. Puedes encadenarlas: dark:hover:bg-zinc-800.
El diseño responsive es mobile-first: una utilidad sin prefijo se aplica en todos los tamaños, y md: la sobrescribe a partir del breakpoint md (48rem por defecto) y hacia arriba. Así, flex-col md:flex-row apila en el móvil y pone en fila desde pantallas medianas.
dark: se aplica, por defecto, cuando el sistema del usuario está en modo oscuro (prefers-color-scheme). Si prefieres un botón que lo cambie a mano, redefine la variante en tu CSS con @custom-variant dark (&:where(.dark, .dark *)); y pasará a depender de una clase .dark.
Úsalo cuando
Para describir todos los estados y tamaños de pantalla de un componente sin salir de su plantilla.
Ten en cuenta
md: significa «desde md hacia arriba», no «solo en tablets». Y en Tailwind v4, hover: solo se aplica en dispositivos que pueden hacer hover: no cuentes con él en una pantalla táctil.
<nav class="flex flex-col gap-2 md:flex-row md:gap-6">
<a class="rounded-lg px-3 py-2 hover:bg-zinc-100 dark:hover:bg-zinc-800"
href="/cursos">Cursos</a>
<button class="rounded-lg bg-sky-600 px-3 py-2 text-white
hover:bg-sky-700 disabled:opacity-50"
[disabled]="enviando()">
Inscribirme
</button>
</nav>Personalizar Tailwind v4 con @theme
En la versión 4, el tema se define en tu CSS, sin archivo de configuración en JavaScript.
- Configuración:
- en el CSS
- tailwind.config.js:
- opcional
En Tailwind v4 todo empieza con una línea de CSS: @import "tailwindcss";. Para personalizarlo, declaras variables dentro de un bloque @theme, y cada una crea sus utilidades: --color-marca-500 hace que existan bg-marca-500, text-marca-500 o border-marca-500.
Ya no necesitas el antiguo tailwind.config.js (se sigue admitiendo con la directiva @config, para proyectos que migran) ni una lista de archivos que analizar: Tailwind los detecta por su cuenta, ignorando lo que esté en tu .gitignore, y con @source añades rutas que no encuentre.
Además, las variables del tema existen como custom properties normales, así que también las usas en tu propio CSS con var(--color-marca-500). Esta app funciona así: su color de acento morado sale de un bloque @theme en su hoja de estilos global.
Úsalo cuando
Para adaptar Tailwind a tu marca: colores, tipografías, breakpoints o sombras propias. En Angular se integra mediante PostCSS, y la documentación de Tailwind tiene una guía para hacerlo.
Ten en cuenta
Si al buscar ayuda encuentras un tailwind.config.js con theme.extend, es la forma de la versión 3. Para un valor puntual que no está en el tema existen los valores arbitrarios, como w-[37rem], pero úsalos con moderación.
@import "tailwindcss";
@theme {
--color-marca-500: oklch(60% 0.25 293);
--color-marca-700: oklch(49% 0.27 293);
--font-titulos: "Fraunces", serif;
--breakpoint-3xl: 120rem;
}
/* Ya existen bg-marca-500, text-marca-700, font-titulos y la variante 3xl: */¿Sabías que…?
Inspecciona cualquier tarjeta de esta lección con las herramientas de desarrollo del navegador: verás clases como rounded-2xl, border-zinc-200 o dark:border-zinc-800. Son las mismas utilidades que estás aprendiendo.
Interactivo
Patio de juegos de Tailwind
Activa utilidades y mira cómo cambia la tarjeta, qué atributo class escribirías y el CSS que Tailwind genera por ti.
Ana Núñez
Desarrolladora frontend
Relleno
Esquinas
Sombra
Fondo y texto
Tamaño de texto
Distribución
Variante hover:
Variante dark:
<div class="p-4 rounded-xl shadow-md bg-white text-zinc-900 text-base flex items-center gap-4">
CSS equivalente de cada utilidad (9)
- p-4padding: 1rem;
- rounded-xlborder-radius: 0.75rem;
- shadow-mdbox-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
- bg-whitebackground-color: var(--color-white);
- text-zinc-900color: var(--color-zinc-900);
- text-basefont-size: 1rem; line-height: 1.5rem;
- flexdisplay: flex;
- items-centeralign-items: center;
- gap-4gap: 1rem;
Cada fondo va con un color de texto que contrasta. bg-accent-600 no viene con Tailwind: lo define esta app en su bloque @theme.
Bootstrap: componentes listos para usar
Bootstrap nació en Twitter en 2011 y durante años fue la forma más rápida de tener una web con buen aspecto. Su propuesta es la contraria a la de Tailwind: componentes ya diseñados que activas con clases como btn o card.
Bootstrap
Un framework de componentes: botones, menús y modales listos, con su propio JavaScript.
- Desde:
- 2011
- JavaScript:
- propio, sin jQuery
Bootstrap te da un catálogo de componentes con diseño propio: btn btn-primary es un botón completo, card una tarjeta y navbar una barra de navegación. También trae utilidades (mt-3, d-flex), pero su fuerte son las piezas ya montadas.
Algunos componentes necesitan comportamiento: abrir un modal, desplegar un menú, mostrar un tooltip. Bootstrap incluye su propio JavaScript, que se activa con atributos como data-bs-toggle="modal", y desde la versión 5 ya no depende de jQuery.
En Angular, en lugar de ese JavaScript, se suele usar ng-bootstrap o ngx-bootstrap: reimplementan los componentes como componentes de Angular y conservan el CSS de Bootstrap.
Úsalo cuando
Para paneles de administración, prototipos o herramientas internas en los que quieres algo correcto y coherente enseguida, sin diseñador.
Ten en cuenta
Las webs con Bootstrap sin personalizar se parecen mucho entre sí. Y su JavaScript modifica el DOM por su cuenta, lo que choca con Angular o React: usa las librerías adaptadas.
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#confirmar">
Borrar cuenta
</button>
<div class="modal fade" id="confirmar" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">¿Seguro que quieres borrar tu cuenta?</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button class="btn btn-danger">Borrar</button>
</div>
</div>
</div>
</div>La rejilla de Bootstrap
container, row y col: doce columnas que se reparten según el ancho de pantalla.
- Columnas:
- 12
- Basada en:
- flexbox
La rejilla (grid) de Bootstrap divide cada fila en 12 columnas. Envuelves el contenido en un .container, cada fila en un .row y cada celda en un .col-* que dice cuántas columnas ocupa: col-6 es la mitad y col-4, un tercio.
Como Tailwind, es mobile-first y tiene breakpoints: sm (576px), md (768px), lg (992px), xl (1200px) y xxl (1400px). col-12 col-md-6 col-lg-4 significa: ancho completo en el móvil, la mitad desde md y un tercio desde lg. Por debajo, usa flexbox.
Úsalo cuando
Para maquetar páginas por filas y columnas cuando ya usas Bootstrap. Con clases como g-3 controlas el espacio entre columnas.
Ten en cuenta
Las columnas de una fila deberían sumar 12 como máximo: si te pasas, las que sobran bajan a otra línea. Para diseños bidimensionales complejos, CSS Grid puede ser más claro.
<div class="container">
<div class="row g-3">
<div class="col-12 col-md-6 col-lg-4">Curso de Angular</div>
<div class="col-12 col-md-6 col-lg-4">Curso de RxJS</div>
<div class="col-12 col-md-6 col-lg-4">Curso de Sass</div>
</div>
</div>Personalizar Bootstrap
Cambia sus variables de Sass al compilar o sus custom properties en el navegador.
Bootstrap está escrito en Sass, y casi todas sus decisiones de diseño son variables con !default: $primary, $border-radius, $font-family-sans-serif… Si les das otro valor antes de cargar Bootstrap, todo el framework se compila con tu marca, incluidos los tonos derivados.
Las versiones recientes también exponen custom properties con el prefijo --bs- (--bs-body-bg, --bs-link-color-rgb), que puedes cambiar sin recompilar, y admiten el modo oscuro con el atributo data-bs-theme="dark".
Úsalo cuando
Sass, para cambiar la paleta o las proporciones a fondo; custom properties, para ajustes en ejecución, como el modo oscuro o un tema por cliente.
Ten en cuenta
Cambiar --bs-primary en ejecución no repinta los botones, que tienen sus propias variables (--bs-btn-bg) calculadas al compilar. Y como Bootstrap 5 carga sus archivos con @import, Dart Sass muestra avisos de obsolescencia al compilarlo: son avisos, no errores.
// Tus valores, antes de cargar Bootstrap
$primary: #6d28d9;
$border-radius: 0.75rem;
$font-family-sans-serif: "Inter", system-ui, sans-serif;
@import "bootstrap/scss/bootstrap";
// En ejecución, sin recompilar
.zona-cliente {
--bs-body-bg: #faf5ff;
--bs-link-color-rgb: 109, 40, 217;
}Interactivo
Tailwind frente a Bootstrap
Activa o desactiva opciones para compararlas cara a cara.
| Característica | Tailwind CSS | Bootstrap |
|---|---|---|
| Filosofía | Utilidades de una sola tarea | Componentes ya diseñados |
| Qué escribes en el HTML | Muchas clases pequeñas: flex p-4 rounded-xl | Pocas clases con significado: btn btn-primary |
| JavaScript | Ninguno: solo CSS | Incluido, para modales, menús y tooltips |
| Aspecto por defecto | Neutro: el diseño lo pones tú | Reconocible: el «aspecto Bootstrap» |
| Cómo se personaliza | Variables en @theme, dentro de tu CSS | Variables de Sass y custom properties --bs- |
| Encaja mejor con | Diseños propios construidos con componentes | Prototipos y paneles internos sin diseñador |
Ponlo en práctica
Saber qué es cada cosa es la mitad del trabajo. La otra mitad es reconocer cuándo usarla.
Interactivo
¿Qué usarías?
Lee cada situación y elige la opción que mejor la resuelve. Fallar aquí no cuenta: es para practicar.
Tu equipo tiene un diseño propio en Figma, trabaja con componentes de Angular y no quiere pelearse con estilos que vienen de fábrica.
Para recordar
- Tailwind te da utilidades de una sola tarea que compones en el HTML; Bootstrap, componentes ya diseñados con su propio JavaScript.
- En Tailwind, las variantes (
hover:,md:,dark:) condicionan cada utilidad, y el diseño responsive es mobile-first. - Tailwind solo genera las clases que encuentra escritas enteras: nunca construyas nombres de clase concatenando texto.
- Tailwind v4 se configura en el CSS con
@theme; Bootstrap, con variables de Sass y custom properties--bs-. - En Angular, usa Bootstrap a través de ng-bootstrap o ngx-bootstrap en lugar de su JavaScript.
Comprueba lo aprendido
Cuestionario
Responde las 5 preguntas para completar la lección.
1.¿Qué significa
md:flex-rowen Tailwind?2.¿Por qué la hoja de estilos de Tailwind suele ser pequeña, aunque existan miles de utilidades?
3.En Tailwind v4, ¿dónde defines un color propio de tu marca?
4.En la rejilla de Bootstrap, ¿qué hace
col-12 col-lg-4?5.En una app Angular quieres usar los modales y desplegables de Bootstrap. ¿Qué es lo más recomendable?