margin: auto como herramienta de alineación
En un contenedor flex, un margen automático absorbe todo el espacio libre antes de que justify-content vea nada. La regla, sus consecuencias y los patrones que solo se resuelven así.
Dentro de un contenedor flex, margin: auto deja de significar “reparte el sobrante a los lados” y pasa a significar “absorbe todo el espacio libre disponible”. Y lo hace antes de que justify-content y align-items entren en juego, lo que le da prioridad sobre ellas. Es la herramienta de alineación individual que flexbox no tiene en el eje principal, y el motivo de que justify-content deje de responder cuando alguien ha puesto un margen automático tres reglas más abajo.
- Enunciar la regla de los márgenes automáticos en flexbox y su prioridad.
- Empujar un elemento al final de una barra sin conocer los demás.
- Centrar en los dos ejes con una sola declaración.
- Diagnosticar el caso en el que
justify-contentdeja de tener efecto.
La regla
La especificación lo dice sin ambigüedad: antes de la alineación mediante justify-content y align-self, cualquier espacio libre positivo se distribuye entre los márgenes automáticos de esa dimensión.
De ahí salen tres consecuencias que conviene tener juntas.
Primera: un margen automático en el eje principal se come todo el espacio libre. Si hay un solo margen automático, se lleva el 100%; si hay varios, se reparten a partes iguales.
Segunda: como el reparto ocurre antes, después no queda espacio libre para que justify-content distribuya. Por eso un solo margin-inline-start: auto en un elemento deja a justify-content: space-between sin efecto visible.
Tercera: en el eje transversal, un margen automático anula el efecto de align-self. Y hay un detalle adicional: un elemento con margen automático en el eje transversal no se estira, aunque align-items valga stretch.
.barra { display: flex; gap: 1rem; }
/* Este elemento y los que le siguen se van al final de la barra */
.derecha { margin-inline-start: auto; }
Los márgenes automáticos absorben espacio libre. Si los elementos no caben y el espacio libre es negativo, los márgenes automáticos se computan a cero y no hacen nada. Un layout que depende de un margen automático para separar dos grupos se junta de golpe en cuanto se estrecha lo suficiente, sin transición.
El separador de barras
El patrón más rentable. Una barra con logotipo, navegación y acciones, donde las acciones deben ir al final independientemente de cuántos elementos de navegación haya.
<header class="barra">
<a class="logo">Marca</a>
<nav class="nav">
<a href="/uno">Uno</a>
<a href="/dos">Dos</a>
</nav>
<div class="acciones">
<button>Entrar</button>
</div>
</header>
.barra {
display: flex;
align-items: center;
gap: 1.5rem;
padding-inline: 1.5rem;
min-block-size: 4rem;
}
.nav { display: flex; gap: 1rem; }
.acciones { margin-inline-start: auto; }
La alternativa con justify-content: space-between funciona solo con exactamente tres grupos y se desmonta al añadir un cuarto. La alternativa con un elemento espaciador vacío añade un nodo sin significado al DOM. El margen automático no tiene ninguno de los dos problemas y se lee como lo que es: “esto va al final”.
Se puede usar más de uno. Con dos márgenes automáticos, el espacio libre se reparte entre ellos:
/* Tres grupos: primero al inicio, segundo centrado, tercero al final */
.grupo-central { margin-inline-start: auto; }
.grupo-final { margin-inline-start: auto; }
Fíjate en que el grupo central queda centrado respecto al espacio sobrante, no respecto al contenedor. Si el primer grupo y el tercero tienen anchos distintos, el central no queda en el centro geométrico. Para eso hace falta grid o un ancho fijo en los laterales.
El centrado perfecto
margin: auto a secas en un elemento flex lo centra en los dos ejes con una sola declaración y sin tocar el contenedor:
.escenario { display: flex; block-size: 100dvh; }
.tarjeta { margin: auto; }
Es más robusto que justify-content: center; align-items: center en un caso concreto e importante: el desbordamiento. Cuando el contenido es más alto que el contenedor, el centrado con align-items corta el contenido por arriba y esa parte es inaccesible incluso con scroll. Con margin: auto, los márgenes automáticos se computan a cero al no haber espacio libre, el elemento se pega al inicio y el desbordamiento se va todo hacia abajo, donde sí se puede alcanzar.
Es el mismo problema que resuelve safe center, con una solución distinta y sin necesidad de una palabra clave reciente.
Cuando justify-content deja de responder
El síntoma: escribes justify-content: space-between en una barra y no pasa nada. Los elementos siguen amontonados o siguen separados de otro modo.
Las tres causas posibles, por frecuencia:
Un margen automático. Alguien puso margin-inline-start: auto en algún hijo, quizá en otra hoja o en una clase de utilidad, y se ha llevado todo el espacio libre. justify-content no tiene nada que distribuir.
Un flex-grow positivo. Si algún elemento crece sin tope, absorbe el espacio libre por el mismo motivo. flex: 1 en cualquier hijo deja justify-content sin efecto.
No hay espacio libre. Los elementos ocupan todo el contenedor o más. Con espacio libre cero o negativo no hay nada que distribuir.
/* Diagnóstico rápido: si al quitar esto space-between vuelve a funcionar,
ya sabes quién se llevaba el espacio */
.hijo { margin-inline-start: auto; }
.otro { flex: 1; }
En DevTools, el atajo es abrir el superpuesto de flex del contenedor: los huecos que dibuja son el espacio libre real, y si no dibuja ninguno, ya tienes la respuesta.
margin: auto existe desde CSS 1 y siempre significó lo mismo: un valor sin determinar que el algoritmo de layout resolvería. En flujo normal, la ecuación de anchos lo usaba como incógnita para cuadrar la suma. Flexbox no inventó nada nuevo: reutilizó la misma incógnita en un algoritmo distinto, y como el algoritmo distinto tiene la noción de espacio libre, el resultado es una herramienta de alineación individual que no existía. Grid hizo exactamente lo mismo después. Este patrón —una propiedad antigua cuyo significado se profundiza al meterla en un contexto nuevo— es constante en la evolución de CSS y merece la pena reconocerlo, porque explica una asimetría de aprendizaje que confunde a mucha gente. margin, display, overflow o position no son propiedades que sepas o no sepas: son propiedades cuyo comportamiento depende del contexto de formato en el que se aplican, y por eso puedes conocerlas durante años y seguir descubriendo cosas. La consecuencia metodológica es concreta: cuando aprendas un modelo de layout nuevo, no te preguntes solo qué propiedades trae, pregúntate qué propiedades viejas cambian de significado dentro de él. Esa segunda lista es siempre más larga que la primera, y es donde están escondidos los patrones que la documentación no destaca.