Un solo módulo de alineación para todos los layouts
Box Alignment Level 3 unificó la alineación de flex, grid, bloque y multicolumna en seis propiedades. Qué es el contenedor de alineación, qué es el sujeto, y qué familia resuelve cada problema.
Durante años, alinear en CSS significaba aprenderse un repertorio de trucos sin relación entre sí: text-align para el texto, vertical-align para las celdas, márgenes automáticos para los bloques, y un position: absolute con desplazamiento negativo para lo demás. El módulo de Box Alignment recogió todo eso en un sistema único de seis propiedades que significan lo mismo en cualquier modo de layout, y entender ese sistema como sistema ahorra memorizar cinco tablas.
- Nombrar las dos familias del módulo y qué distribuye cada una.
- Distinguir el contenedor de alineación del sujeto de alineación en cada modo de layout.
- Saber qué propiedades tienen efecto en flex, en grid y en bloque, y cuáles se ignoran.
- Explicar por qué
gappertenece a este módulo y no a Grid.
Dos familias, no seis propiedades sueltas
El módulo define dos operaciones distintas y le da a cada una un par de propiedades.
La distribución de contenido (justify-content y align-content) coloca el conjunto de los sujetos dentro del contenedor y decide qué se hace con el espacio sobrante: pegarlo a un lado, centrarlo o repartirlo entre los sujetos. Es una propiedad del contenedor porque habla de todos a la vez.
La autoalineación (justify-self y align-self, con sus valores por defecto justify-items y align-items declarados en el contenedor) coloca cada sujeto dentro del área que le ha tocado. Es una propiedad de cada elemento porque cada uno puede querer una cosa distinta.
La distinción no es formal, es operativa: si el espacio sobrante está entre los elementos, es distribución de contenido; si está alrededor de uno de ellos dentro de su hueco, es autoalineación. En una rejilla las dos existen a la vez y son independientes: puedes centrar el bloque de pistas dentro del contenedor con justify-content y a la vez alinear cada elemento a la izquierda de su celda con justify-items.
.rejilla {
display: grid;
grid-template-columns: repeat(3, 10rem); /* pistas fijas: sobra espacio */
gap: 1rem;
justify-content: center; /* el bloque de 3 pistas, centrado en el contenedor */
justify-items: start; /* cada elemento, pegado al inicio de SU celda */
}
Contenedor de alineación y sujeto
La especificación habla de un contenedor de alineación (el rectángulo dentro del cual se coloca algo) y de un sujeto de alineación (lo que se coloca). Lo que cambia entre modos de layout no son las propiedades: es a qué corresponde cada uno de esos dos papeles.
| Modo | Contenedor de alineación | Sujeto |
|---|---|---|
| Flex, distribución | la línea de flex | el conjunto de ítems de esa línea |
| Flex, autoalineación | la línea de flex en el eje transversal | cada ítem |
| Grid, distribución | la caja de contenido de la rejilla | el conjunto de pistas |
| Grid, autoalineación | el área de rejilla del elemento | cada elemento |
| Bloque | la caja de contenido del contenedor | el conjunto de cajas en flujo |
Esta tabla explica la mayoría de las sorpresas. Por ejemplo, que justify-content en Grid mueva las pistas y no los elementos: si tus pistas son 1fr no sobra espacio, las pistas ya ocupan todo, y justify-content no tiene ningún efecto visible. La gente concluye que “no funciona” cuando lo que ocurre es que el sujeto que iba a mover ya llena el contenedor.
Si una propiedad de distribución no hace nada, pregúntate si hay espacio sobrante. justify-content con pistas 1fr, align-content en un flex de una sola línea o align-content en un bloque de altura automática son los tres casos donde no sobra nada por definición y por tanto no hay nada que distribuir.
Qué tiene efecto en cada modo
No todas las propiedades se aplican en todos los layouts, y las exclusiones tienen motivo.
| Propiedad | Flexbox | Grid | Bloque |
|---|---|---|---|
justify-content |
sí, eje principal | sí, eje en línea | no aplica |
align-content |
sí, solo con varias líneas | sí, eje de bloque | sí, desde 2024 |
justify-items |
ignorada | sí, eje en línea | no aplica |
align-items |
sí, eje transversal | sí, eje de bloque | no aplica |
justify-self |
ignorada | sí, eje en línea | no aplica |
align-self |
sí, eje transversal | sí, eje de bloque | no aplica |
Las dos casillas de “ignorada” en Flexbox son las que más confunden y tienen una explicación limpia: en el eje principal de un contenedor flex, el tamaño de cada ítem ya lo determina el algoritmo de crecimiento y encogimiento. No existe un “hueco asignado” dentro del cual alinear el ítem, porque el ítem es el hueco. Por eso el eje principal solo admite distribución de contenido y por eso el equivalente a justify-self en Flexbox son los márgenes automáticos, que sí participan en el reparto de espacio libre.
En layout de bloque, la alineación en el eje en línea se sigue haciendo con margin-inline: auto, que lleva funcionando desde siempre y no necesita sustituto.
Por qué gap vive aquí
gap, row-gap y column-gap son propiedades de este módulo, no de Grid, aunque llegaran primero a Grid con el nombre grid-gap. La razón es conceptual: el hueco es espacio reservado antes de repartir el sobrante, y por tanto forma parte del mismo cálculo que la distribución de contenido. Por eso space-between reparte lo que queda después de aplicar los gap, y por eso los dos mecanismos se combinan sin pelearse.
Que sea un módulo transversal es lo que permitió que gap llegara a Flexbox en 2021 y a multicolumna sin reinventar nada: la definición ya estaba escrita para cualquier contenedor.
Antes de Box Alignment, cada modo de layout traía su propio vocabulario de alineación, y eso tenía una consecuencia que nadie nombraba: no se podía razonar sobre alineación sin saber antes qué modo de layout tenías delante. Cambiar un contenedor de flex a grid obligaba a reescribir la alineación entera, aunque la intención de diseño —“esto va centrado, aquello pegado al final”— no hubiera cambiado ni un ápice. El módulo unificado separa la intención del mecanismo: place-items: center significa lo mismo en los cuatro modos, y por tanto sobrevive a que cambies el modo. Ese es el patrón que se repite en toda la evolución moderna de CSS —gap, las propiedades lógicas, color-mix(), las funciones de color con from—: coger capacidades que existían atadas a un contexto concreto y extraerlas a un módulo ortogonal que se pueda combinar con todo lo demás. Cuando estudies una característica nueva, la pregunta que más rendimiento da no es qué hace, sino de qué contexto la han desatado; ahí es donde está el poder que la especificación acaba de repartir.