Box model
Si alguna vez te ha pasado que un elemento es más grande de lo que esperabas, o que dos secciones se pegan cuando no deberían, el problema casi seguro está en el box model. Es el concepto más importante de CSS para entender cómo se calcula el tamaño y el espaciado de todo.
Cada elemento es una caja
En CSS, todo elemento HTML es una caja rectangular. Da igual que sea un <h1>, un <p>, una <img> o un <div>. Cada caja tiene cuatro capas, de dentro hacia fuera:
- Content: el contenido real (texto, imagen, etc.).
- Padding: espacio interior entre el contenido y el borde. El fondo del elemento llega hasta aquí.
- Border: el borde visible (o invisible) de la caja.
- Margin: espacio exterior entre este elemento y los que lo rodean. Siempre transparente.
.product-card {
/* Content: determinado por el contenido y width/height */
width: 300px;
/* Padding: espacio interior */
padding: 1.5rem;
/* Border: borde visible */
border: 2px solid #333;
/* Margin: espacio exterior */
margin: 1rem;
}
Abre las DevTools (F12), selecciona cualquier elemento y mira la pestaña "Computed". Verás un diagrama con las 4 capas y sus valores exactos. Úsalo constantemente.
El problema del box-sizing por defecto
Por defecto, CSS usa box-sizing: content-box. Esto significa que width y height solo afectan al contenido. El padding y el border se suman por encima:
/* content-box (por defecto) */
.caja {
width: 300px;
padding: 20px;
border: 2px solid #333;
}
/* Ancho total REAL: 300 + 20 + 20 + 2 + 2 = 344px 😤 */
Nadie quiere estar haciendo sumas. La solución es box-sizing: border-box, que hace que width incluya padding y border:
/* border-box: width incluye todo */
.caja {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
}
/* Ancho total REAL: 300px. El contenido se ajusta automáticamente. ✅ */
Aplícalo a todo el documento con el reset universal:
*, *::before, *::after {
box-sizing: border-box;
}
Este reset es tan estándar que si no lo pones, estás buscando problemas. Todo framework y librería CSS lo incluye.
Padding: espacio interior
El padding crea espacio entre el contenido y el borde. El fondo del elemento se muestra en el área de padding:
.notification {
background: #1e293b;
border-radius: 8px;
/* Las 4 direcciones a la vez */
padding: 1rem;
/* Vertical | Horizontal */
padding: 1rem 1.5rem;
/* Top | Horizontal | Bottom */
padding: 0.5rem 1.5rem 1rem;
/* Top | Right | Bottom | Left (sentido reloj) */
padding: 0.5rem 1.5rem 1rem 1.5rem;
}
Logical properties (la forma moderna)
En lugar de top/right/bottom/left, CSS moderno usa propiedades lógicas que se adaptan a cualquier dirección de escritura (LTR, RTL, vertical):
.notification {
/* padding-top + padding-bottom */
padding-block: 1rem;
/* padding-left + padding-right */
padding-inline: 1.5rem;
/* Solo arriba */
padding-block-start: 0.5rem;
/* Solo derecha (en LTR) / izquierda (en RTL) */
padding-inline-end: 2rem;
}
Usa padding-block y padding-inline como norma. Si tu web se traduce al árabe o hebreo, el layout se adapta automáticamente.
Margin: espacio exterior
El margin crea espacio entre el elemento y sus vecinos. Funciona con la misma sintaxis que padding:
.section {
margin-block: 3rem;
}
.card {
margin-block-end: 1.5rem;
}
/* Centrar un elemento horizontalmente */
.container {
max-width: 1200px;
margin-inline: auto;
}
margin-inline: auto es la forma clásica de centrar un bloque horizontalmente. El navegador reparte el espacio sobrante a partes iguales a izquierda y derecha.
Colapso de márgenes
Uno de los comportamientos más confusos de CSS: cuando dos márgenes verticales se tocan, no se suman, se colapsan. El margen resultante es el mayor de los dos:
h2 {
margin-block-end: 1.5rem; /* 1.5rem abajo */
}
p {
margin-block-start: 1rem; /* 1rem arriba */
}
/* Espacio real entre h2 y p: 1.5rem (no 2.5rem) */
El colapso solo ocurre con márgenes verticales (block) entre elementos hermanos o entre padre e hijo si no hay padding, border o contenido que los separe.
No ocurre con:
- Elementos flex o grid (los hijos no colapsan).
- Márgenes horizontales (inline).
- Elementos con
overflowdistinto devisible.
Truco práctico: si el colapso de márgenes te confunde, usa
gapcon flexbox o grid en lugar de márgenes individuales. Sin colapso, sin sorpresas.
Border: el borde
.card {
/* Shorthand: grosor estilo color */
border: 1px solid #333;
/* Solo un lado */
border-inline-start: 3px solid #ff6b35;
/* Solo abajo */
border-block-end: 1px solid #222;
/* Bordes redondeados */
border-radius: 12px;
/* Círculo perfecto */
border-radius: 50%;
}
Outline vs Border
outline se parece a border pero no ocupa espacio en el layout. No cambia el tamaño del elemento:
.input:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
El outline se usa principalmente para indicar el foco del teclado. Nunca lo quites sin poner una alternativa visible — es un desastre de accesibilidad.
Width y height
.sidebar {
width: 280px; /* Ancho fijo */
min-width: 200px; /* No más estrecho que esto */
max-width: 400px; /* No más ancho que esto */
}
.hero {
min-height: 100dvh; /* Al menos la altura del viewport */
}
.article-body {
max-width: 65ch; /* Máximo 65 caracteres por línea — legibilidad óptima */
}
Evita usar height fijo en elementos con texto. Si el contenido crece, se desborda. Usa min-height en su lugar.
Display: block vs inline vs inline-block
Cada elemento tiene un display por defecto que determina cómo se comporta:
| Display | Comportamiento | Ejemplos |
|---|---|---|
block |
Ocupa todo el ancho disponible, empieza en línea nueva | div, p, h1, section |
inline |
Solo ocupa lo necesario, no acepta width/height ni margin vertical | span, a, strong, em |
inline-block |
Fluye con el texto pero acepta width, height y margin | img, badges, botones inline |
/* Convertir un enlace en un botón con tamaño */
.btn {
display: inline-block;
padding: 0.75rem 1.5rem;
background: #ff6b35;
color: #fff;
border-radius: 8px;
text-decoration: none;
}
Construye cards de producto con box model
Crea una página con 3 cards de producto para una tienda de sneakers. Cada card debe tener:
- Un contenedor
.cardconwidth: 320px,box-sizing: border-box, borde sutil y border-radius - Padding interno de
1.5rem - Un borde izquierdo (
border-inline-start) de 4px con un color de acento diferente por card - Margin entre cards usando
margin-block-end - Un botón
.btncondisplay: inline-blocky padding - Un contenedor
.containercentrado conmax-widthymargin-inline: auto
Abre DevTools y revisa el diagrama del box model de cada card. Comprueba que border-box hace que el width sea exactamente 320px.
lightbulb Pistas
Usa logical properties (padding-block, margin-inline, border-inline-start) en lugar de las físicas. Para poner 3 cards verticales, basta con ponerlas una detrás de otra en el HTML — son elementos block, cada una ocupa su propia línea.