Tema
El modelo de caja
En CSS todo es una caja: un párrafo, una imagen, un botón, incluso cada palabra dentro de un enlace. Entender cómo se calcula el tamaño de esas cajas (contenido, relleno, borde y margen) es lo que te permite maquetar con precisión en lugar de "mover cosas hasta que queden".
Concepto
Cada elemento se dibuja como un rectángulo con cuatro capas, de dentro hacia fuera:
txt
┌─────────────────── margin (espacio exterior, transparente) ───────────────────┐
│ ┌──────────────── border (el borde) ─────────────────────────────────────┐ │
│ │ ┌───────────── padding (relleno interior, toma el fondo) ──────────┐ │ │
│ │ │ │ │ │
│ │ │ content (texto, imagen; width × height) │ │ │
│ │ │ │ │ │
│ │ └───────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘Analogía
Un cuadro colgado en la pared: la pintura es el contenido, el paspartú (cartón blanco alrededor) es el padding, el marco es el border y el espacio en la pared hasta el siguiente cuadro es el margin.
Juega con los valores y observa cómo cambia el tamaño total:
Padding, border y margin
css
.tarjeta {
/* padding: espacio interior */
padding: 24px; /* los 4 lados */
padding: 16px 24px; /* vertical | horizontal */
padding: 8px 16px 24px; /* arriba | horizontal | abajo */
padding: 8px 16px 24px 32px; /* arriba | derecha | abajo | izquierda (sentido del reloj) */
padding-top: 8px; /* lados individuales */
/* border: grosor, estilo, color */
border: 1px solid #e2e8f0;
border-bottom: 3px dashed #7c3aed;
/* estilos: solid, dashed, dotted, double, none */
/* margin: espacio exterior */
margin: 0 auto; /* auto en horizontal centra un bloque con ancho definido */
margin-bottom: 2rem;
}Truco para recordar el orden de 4 valores: TRBL ("trouble"): Top, Right, Bottom, Left.
Propiedades lógicas
Las propiedades lógicas funcionan según la dirección del texto (útil para sitios en árabe o hebreo) y son más cortas para un eje:
css
.caja {
margin-inline: auto; /* izquierda y derecha */
padding-block: 2rem; /* arriba y abajo */
padding-inline: 1rem 2rem; /* inicio y fin */
border-inline-start: 4px solid teal; /* borde izquierdo en español */
}box-sizing: el detalle que lo cambia todo
Por defecto (content-box), width define sólo el contenido. El padding y el borde se suman:
css
.caja {
width: 300px;
padding: 20px;
border: 5px solid;
/* Ancho real visible: 300 + 20 + 20 + 5 + 5 = 350px 😱 */
}Con border-box, width incluye contenido + padding + borde:
css
.caja {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 5px solid;
/* Ancho real visible: 300px. El contenido se ajusta a 250px 👍 */
}Por eso todos los proyectos profesionales empiezan con:
css
*,
*::before,
*::after {
box-sizing: border-box;
}Buena práctica
Incluye esa regla siempre, en la primera línea de tu CSS (ya viene en el reset de la lección 1). Hace que width: 50% con padding siga midiendo exactamente 50 %.
width, height y sus límites
css
.contenedor {
width: 100%;
max-width: 1200px; /* nunca más ancho que esto */
margin-inline: auto; /* centrado */
}
.hero {
min-height: 60vh; /* al menos esta altura, pero crece si hay más contenido */
}
.imagen {
max-width: 100%; /* nunca se desborda de su contenedor */
height: auto; /* conserva la proporción */
}
.cuadro {
aspect-ratio: 16 / 9; /* alto calculado automáticamente según el ancho */
width: 100%;
}Error común
Poner height fija a elementos con texto (height: 200px en una tarjeta). Cuando el cliente escriba un texto más largo o se vea en móvil, el contenido se desbordará. Usa min-height o deja que el contenido defina la altura.
Colapso de márgenes
Los márgenes verticales entre bloques adyacentes no se suman: se toma el mayor.
css
h2 { margin-bottom: 30px; }
p { margin-top: 20px; }
/* Espacio entre el h2 y el p: 30px, no 50px */También ocurre entre un padre y su primer/último hijo si el padre no tiene borde ni padding: el margen del hijo "se sale" del padre.
css
.tarjeta { background: #eee; }
.tarjeta h3 { margin-top: 40px; } /* ¡el margen aparece FUERA de la tarjeta! */Soluciones: dar padding al padre, o usar display: flex/grid en el padre (dentro de flex y grid los márgenes no colapsan). En layouts modernos se usa mucho gap en lugar de márgenes, lo que evita el problema.
Patrón profesional: espaciado en una sola dirección
Aplica los márgenes sólo hacia abajo (margin-bottom) o usa el "búho lobotomizado" para separar hermanos:
css
.flujo > * + * {
margin-top: 1em; /* espacio sólo ENTRE elementos, no antes del primero */
}overflow: cuando el contenido no cabe
css
.caja {
overflow: visible; /* por defecto: el contenido se sale */
overflow: hidden; /* recorta lo que sobresale */
overflow: auto; /* barra de scroll sólo si hace falta */
overflow: scroll; /* siempre barra de scroll */
overflow-x: auto; /* sólo horizontal: ideal para tablas en móvil */
}css
/* Tabla responsive: se desplaza horizontalmente en pantallas pequeñas */
.tabla-contenedor {
overflow-x: auto;
}border-radius y outline
css
.boton { border-radius: 8px; }
.pildora { border-radius: 999px; } /* extremos redondos */
.avatar { border-radius: 50%; } /* círculo (si es cuadrado) */
.esquina { border-radius: 16px 16px 0 0; } /* sólo arriba */
/* outline: como un borde, pero NO ocupa espacio ni afecta el layout */
.boton:focus-visible {
outline: 3px solid #7c3aed;
outline-offset: 3px; /* separación del borde */
}Accesibilidad
Nunca pongas outline: none en los elementos enfocables sin dar un estilo de foco alternativo. Quienes navegan con teclado necesitan ver dónde están.
Ejemplo completo: tarjeta de servicio
html
<article class="servicio">
<img src="img/diseno.webp" alt="" class="servicio__img">
<div class="servicio__cuerpo">
<h3>Diseño web</h3>
<p>Sitios modernos, rápidos y adaptados a cualquier dispositivo.</p>
<a href="#contacto" class="servicio__enlace">Cotizar</a>
</div>
</article>css
*, *::before, *::after { box-sizing: border-box; }
.servicio {
max-width: 340px;
border: 1px solid #e5e7eb;
border-radius: 16px;
overflow: hidden; /* recorta la imagen con las esquinas redondeadas */
background: #fff;
}
.servicio__img {
display: block; /* quita el espacio fantasma bajo las imágenes inline */
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover; /* recorta la imagen sin deformarla */
}
.servicio__cuerpo {
padding: 1.5rem;
}
.servicio__cuerpo h3 {
margin: 0 0 0.5rem;
}
.servicio__cuerpo p {
margin: 0 0 1.25rem;
color: #4b5563;
}
.servicio__enlace {
display: inline-block; /* para que el padding vertical funcione */
padding: 0.6rem 1.2rem;
border: 2px solid #7c3aed;
border-radius: 8px;
color: #7c3aed;
font-weight: 600;
text-decoration: none;
}Ejercicios
- Con
content-box, una caja tienewidth: 200px; padding: 15px; border: 5px solid. ¿Cuánto mide en total? ¿Y conborder-box? - Crea un contenedor centrado de máximo 960px con 1rem de padding lateral.
- Un
h2tienemargin-bottom: 24pxy elpsiguientemargin-top: 16px. ¿Cuál es la separación? - Crea un avatar circular de 64px con un borde blanco de 3px y un anillo de foco morado al recibir foco.
Ver solución
content-box: 200 + 15×2 + 5×2 = 240px.border-box: 200px (el contenido queda en 160px).
css
.contenedor {
max-width: 960px;
margin-inline: auto;
padding-inline: 1rem;
}24px: los márgenes verticales colapsan y gana el mayor.
css
.avatar {
width: 64px;
height: 64px;
border-radius: 50%;
border: 3px solid white;
object-fit: cover;
}
.avatar:focus-visible {
outline: 3px solid #7c3aed;
outline-offset: 2px;
}Resumen
- Toda caja tiene content, padding, border y margin.
- Usa siempre
box-sizing: border-boxpara quewidthincluya padding y borde. - Prefiere
max-widthymin-heighta medidas fijas. - Los márgenes verticales colapsan (gana el mayor); en flex y grid no.
overflowcontrola el contenido que no cabe;outlineno ocupa espacio.- Nunca elimines el foco visible sin reemplazarlo.
Siguiente: Display y posicionamiento.