Márgenes auto, negativos, en porcentaje y lógicos
Cómo reparte el espacio sobrante un margen automático en cada modelo de layout, qué hacen de verdad los negativos, por qué los porcentajes se resuelven contra el tamaño en línea, y por qué todo el nivel hablaba de ejes lógicos.
Quedan cuatro comportamientos del margen que no son colapso y que explican la mayoría de las sorpresas restantes: el valor auto significa cosas distintas según el modelo de layout, los negativos no encogen la caja sino que la desplazan, los porcentajes se resuelven contra una dimensión que no es la que esperas, y todo lo que has leído en este nivel estaba escrito en ejes lógicos aunque hablásemos de arriba y abajo.
- Predecir qué hace
margin: autoen flujo, en flex, en grid y en posicionamiento absoluto. - Usar márgenes negativos sabiendo qué caja mueven y cuál no.
- Explicar por qué un margen en porcentaje se resuelve contra el ancho.
- Reescribir el modelo de caja en ejes lógicos y saber qué cambia en vertical.
margin auto y el reparto del espacio
Un margen auto no vale cero: absorbe el espacio sobrante. Lo que cambia entre modelos de layout es cuánto espacio hay disponible para absorber y en qué ejes.
En flujo de bloque, el espacio sobrante existe solo en el eje en línea, y solo si el elemento tiene un tamaño definido. De ahí el centrado clásico:
.contenido {
inline-size: min(65ch, 100%);
margin-inline: auto; /* reparte el sobrante a los dos lados */
}
Y de ahí también la limitación que ha frustrado a generaciones: en flujo normal, un margen automático en el eje de bloque computa a cero. No hay espacio sobrante vertical que repartir, porque la altura del contenedor la determina su contenido. Por eso margin-block: auto no centra verticalmente en flujo.
En flex y en grid, sí lo hay, y en los dos ejes:
.barra { display: flex; min-block-size: 4rem; }
/* Empuja este elemento y los siguientes al final de la fila. */
.barra .a-la-derecha { margin-inline-start: auto; }
/* Y esto si centra verticalmente. */
.barra .centrado { margin-block: auto; }
Hay un detalle de precedencia que merece la pena conocer porque produce un “no me funciona justify-content” muy frecuente: los márgenes automáticos absorben el espacio libre antes de que se aplique la alineación. Si un elemento flex tiene un margen auto en el eje principal, no queda espacio libre que repartir y justify-content deja de tener efecto en ese eje.
En posicionamiento absoluto, con las dos posiciones fijadas y un tamaño definido, los márgenes automáticos reparten el sobrante y centran en ambos ejes:
.dialogo {
position: absolute;
inset: 0;
inline-size: 20rem;
block-size: 12rem;
margin: auto; /* centrado en los dos ejes */
}
Los márgenes negativos
Un margen negativo no encoge la caja: mueve la arista de la que habla. En el lado de inicio arrastra el elemento hacia atrás; en el lado de final acerca lo que venga después.
Y hay un caso especial que sigue siendo útil: cuando el tamaño en línea es automático, un margen negativo en el eje en línea ensancha la caja, porque el ancho se calcula como lo que queda tras restar los márgenes, y restar un negativo suma.
/* Sangrado a los lados, dentro de un contenedor con relleno. */
.sangrado-lateral {
margin-inline: -1rem; /* la caja se ensancha 2rem */
}
Para el sangrado a ancho completo dentro de una columna de texto, la versión con calc() sobre unidades de ventana tiene un defecto conocido —100vw incluye la barra de desplazamiento y provoca desbordamiento horizontal—, así que hoy la respuesta correcta no usa márgenes negativos en absoluto: la pone el contenedor.
.articulo {
display: grid;
grid-template-columns: 1fr min(65ch, 100%) 1fr;
}
.articulo > * { grid-column: 2; }
.articulo > .ancho-completo { grid-column: 1 / -1; }
Es el mismo cambio de propietario de la lección anterior: en lugar de que el elemento se escape de su contenedor tirando de sus márgenes, el contenedor declara que existe una pista de ancho completo y quien la quiera la ocupa.
Un margen negativo participa en el colapso con todas las reglas que ya viste: el resultado es el mayor positivo más el más negativo. Eso significa que un margen negativo puesto para acercar dos elementos puede acabar fundido con otro y producir un desplazamiento que no es el que calculaste. Si necesitas un desplazamiento exacto y predecible, translate no colapsa con nada y además no afecta al layout.
Los porcentajes se resuelven contra el tamaño en línea
Un margen o un relleno en porcentaje se resuelve contra el tamaño en línea del bloque contenedor. Los cuatro lados. También los del eje de bloque.
.caja { padding-block-start: 10%; }
/* Ese 10% es el 10% del ANCHO del contenedor, no de su alto. */
La razón es evitar una dependencia circular. La altura de un contenedor en flujo normal la determina normalmente su contenido; si el margen superior de un hijo se resolviera contra la altura del padre, esa altura dependería de un valor que a su vez depende de ella. El tamaño en línea, en cambio, se resuelve antes y de forma independiente, así que es la única dimensión disponible sin circularidad.
De esa regla salió durante quince años el truco de la proporción fija:
/* El truco historico: 9/16 = 0.5625 */
.video-antiguo { position: relative; padding-block-start: 56.25%; }
.video-antiguo > iframe { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; }
/* La forma moderna, que ya no necesita ningun truco. */
.video { aspect-ratio: 16 / 9; }
Merece la pena conocer el truco aunque no lo escribas, porque sigue vivo en muchísimo código heredado y porque explica de dónde salen esos padding-top con decimales raros que aparecen sin comentario.
Las propiedades lógicas y el eje de bloque
Todo este nivel está escrito en propiedades lógicas y no es una preferencia estética. margin-block y margin-inline no son sinónimos de vertical y horizontal: son el eje del flujo de bloque y el eje del texto, y en un modo de escritura vertical intercambian su orientación física.
| Lógica | Física en horizontal | Física en vertical de derecha a izquierda |
|---|---|---|
margin-block-start |
margin-top |
margin-right |
margin-block-end |
margin-bottom |
margin-left |
margin-inline-start |
margin-left en izquierda a derecha |
margin-top |
inline-size |
width |
height |
block-size |
height |
width |
Y aquí está lo que cierra el nivel: el colapso de márgenes ocurre en el eje de bloque, no en el vertical. En writing-mode: vertical-rl, los márgenes que colapsan son los horizontales, porque el flujo de bloque va de derecha a izquierda. Lo mismo con los porcentajes: se resuelven contra el tamaño en línea, que en modo vertical es la altura del contenedor.
.columna-vertical {
writing-mode: vertical-rl;
}
/* Dentro de aqui, margin-block es horizontal, y es el que colapsa. */
La forma en que aprendimos CSS invierte la relación real entre los dos vocabularios. Todo el mundo aprende margin-top y width primero, y descubre después que existen unas propiedades lógicas para casos exóticos con árabe o japonés. La realidad de la especificación es la contraria: el modelo está definido en ejes lógicos y las propiedades físicas son un caso particular que resulta coincidir con lo lógico en el modo de escritura que usa la mayoría del contenido occidental. El colapso de márgenes no está definido como “los márgenes verticales se funden”: está definido sobre el eje de bloque, y si giras el modo de escritura, giran los márgenes que colapsan. Los porcentajes no se resuelven contra el ancho: se resuelven contra el tamaño en línea, que casualmente es el ancho la mayor parte del tiempo. El margen automático no reparte espacio horizontal: reparte el espacio del eje que tenga sobrante, y en flujo normal ese es el eje en línea. Interiorizar la dirección correcta de esa relación tiene un efecto práctico inmediato y otro más lento. El inmediato es que muchas reglas que parecían arbitrarias dejan de serlo, porque estaban enunciadas en un vocabulario que no es el suyo: en cuanto reformulas “los márgenes verticales colapsan” como “los márgenes del eje de bloque colapsan”, la regla encaja con las otras dos y las tres se explican con el mismo esquema. El lento es de coste de mantenimiento: escribir propiedades físicas en un producto que algún día se traduzca al árabe o al hebreo garantiza una reescritura completa de la hoja de estilos, mientras que escribir propiedades lógicas hoy no cuesta ni un carácter más ni un milisegundo más y hace que ese día sea un cambio de un atributo dir en el html. No es previsión: es escribir en el vocabulario en el que el lenguaje ya estaba pensando.
- Comprueba que
margin-block: autono centra en flujo y sí lo hace en un elemento flex. - Pon un margen automático en el eje principal de un flex y verifica que
justify-contentdeja de tener efecto. - Mide un
padding-block-start: 10%y confirma que se resuelve contra el ancho. - Sustituye un sangrado a ancho completo hecho con márgenes negativos por la versión con pistas de rejilla.
- Aplica
writing-mode: vertical-rla un bloque con márgenes y observa cuáles colapsan.