wandres.dev
FLEXBOX: EL ALGORITMO · Base, crecer, encoger

flex-basis: el tamaño de partida

Qué es el tamaño base de un elemento flex, cómo se determina, quién gana entre flex-basis y width, y por qué flex-basis 0 y flex-basis auto producen layouts completamente distintos.

⏱ 18 min

El algoritmo de flexbox tiene tres fases: se calcula un tamaño de partida para cada elemento, se mide cuánto espacio sobra o falta, y se reparte esa diferencia. flex-basis gobierna la primera fase, y como las otras dos operan sobre su resultado, es el parámetro que más determina el layout final. También es el que casi nadie escribe explícitamente, porque va escondido dentro de la abreviatura flex.

🎯 Al terminar esta lección sabrás
  • Definir el tamaño base y el tamaño hipotético de un elemento flex.
  • Ordenar la precedencia entre flex-basis, inline-size y el contenido.
  • Distinguir flex-basis: 0 de flex-basis: auto con un ejemplo numérico.
  • Explicar por qué flex-basis opera sobre el eje principal y no sobre el ancho.

El tamaño base

Cada elemento flex tiene un tamaño base: el tamaño que tendría en el eje principal antes de crecer o encoger. Es la entrada del algoritmo, no su salida.

flex-basis acepta cuatro tipos de valor y cada uno da un tamaño base distinto:

Una longitud o un porcentaje, como flex-basis: 20rem o flex-basis: 30%, fija el tamaño base directamente. El porcentaje se resuelve contra el tamaño en el eje principal del contenedor.

flex-basis: content usa el tamaño intrínseco del contenido, ignorando cualquier inline-size que el elemento tenga.

flex-basis: auto, el valor inicial, delega en la propiedad de tamaño del eje principal: mira inline-size si el eje principal es el eje en línea, o block-size si es el de bloque. Si esa propiedad también vale auto, entonces se comporta como content.

flex-basis: 0 fija el tamaño base a cero, lo que en la práctica significa que el contenido no cuenta para el reparto.

.contenedor { display: flex; }

/* base 20rem: el contenido no influye en el punto de partida */
.a { flex-basis: 20rem; }

/* base auto: mira inline-size, que vale 15rem */
.b { flex-basis: auto; inline-size: 15rem; }

/* base content: ignora el inline-size y mide el contenido */
.c { flex-basis: content; inline-size: 15rem; }

/* base cero: parte de la nada */
.d { flex-basis: 0; }
📝
flex-basis va en el eje principal, no en el ancho

Con flex-direction: column, flex-basis: 20rem fija una altura base, no una anchura. La abreviatura flex: 1 1 20rem significa cosas distintas según la dirección del contenedor, y ese es uno de los motivos por los que cambiar row por column a veces destroza un layout entero.

Quién gana entre flex-basis y width

La precedencia está definida y es sencilla, pero se olvida constantemente: flex-basis gana a la propiedad de tamaño cuando tiene un valor distinto de auto.

/* La base es 10rem. El inline-size se ignora por completo. */
.elemento { flex-basis: 10rem; inline-size: 30rem; }

Esto sorprende sobre todo cuando llega por la abreviatura. flex: 1 expande a flex: 1 1 0%, con lo que pone flex-basis: 0% y anula cualquier inline-size que hubieras escrito. Es la causa más frecuente de “le he puesto un ancho y no lo respeta”.

Lo que no se ignora son min-inline-size y max-inline-size. Esos siguen aplicándose al final y recortan el resultado, pasara lo que pasara con la base. Ese es el mecanismo que usarás para poner límites a un elemento flexible sin renunciar a la flexibilidad.

/* Crece y encoge libremente, pero nunca fuera de este rango */
.panel {
  flex: 1 1 0;
  min-inline-size: 12rem;
  max-inline-size: 40rem;
}

Cero frente a auto, con números

La diferencia entre flex-basis: 0 y flex-basis: auto es la decisión de diseño más consecuente de todo flexbox, y se ve mejor con un caso concreto.

Contenedor de 600px, tres elementos con flex-grow: 1, cuyos contenidos miden respectivamente 100px, 200px y 300px en max-content.

Con flex-basis: auto, las bases son 100, 200 y 300, que suman 600. No sobra espacio, así que flex-grow no reparte nada y los elementos quedan con sus tamaños de contenido: 100, 200 y 300. Proporcionales al contenido.

Con flex-basis: 0, las bases son 0, 0 y 0, que suman 0. Sobran los 600px enteros y flex-grow: 1 los reparte a partes iguales: 200, 200 y 200. Iguales entre sí, independientemente del contenido.

/* Columnas del mismo tamaño, mida lo que mida el contenido */
.iguales > * { flex: 1 1 0; }

/* Columnas proporcionales al contenido, repartiendo solo el sobrante */
.proporcionales > * { flex: 1 1 auto; }

La regla mnemotécnica que funciona: cero reparte el espacio total, auto reparte el espacio sobrante. Si quieres columnas idénticas, base cero. Si quieres que el contenido influya, base auto.

El tamaño hipotético y la unidad de flexibilidad

Un par de matices que aparecen en cuanto lees la especificación y que conviene tener claros.

El tamaño hipotético de un elemento es su tamaño base ya recortado por min-inline-size y max-inline-size, pero antes de aplicar crecimiento o encogimiento. La suma de los tamaños hipotéticos es lo que se compara con el tamaño del contenedor para decidir si hay que crecer o encoger. Es un paso intermedio, pero es el que decide qué rama del algoritmo se ejecuta.

Y una precisión sobre las unidades: flex-basis: 0 sin unidad es válido y es lo que escribe la mayoría, pero durante años se recomendó flex-basis: 0% por un bug antiguo de IE 11 que ya no le importa a nadie. La abreviatura flex: 1 expande a 0% por herencia de esa historia. Hoy 0, 0px y 0% son equivalentes en la práctica.

/* Estas tres son equivalentes en todos los motores actuales */
.a { flex: 1; }          /* 1 1 0% */
.b { flex: 1 1 0; }
.c { flex-grow: 1; flex-shrink: 1; flex-basis: 0; }
flex-basis es la única propiedad que decide si tu layout es de contenido o de contenedor

Toda la discusión sobre flexbox contra grid, sobre layouts intrínsecos, sobre diseño con o sin puntos de ruptura, se reduce en flexbox a un solo parámetro. Con flex-basis: 0 estás declarando que el contenedor manda: reparte su espacio en fracciones y el contenido se acomoda como pueda. Es el modelo de rejilla, es lo que hace 1fr en grid, y es el que produce alineaciones limpias entre componentes distintos. Con flex-basis: auto estás declarando que el contenido manda: cada elemento parte de lo que necesita y solo se negocia lo que sobra. Es el modelo tipográfico, el que produce menús cuyos elementos ocupan lo que ocupa su palabra, y el que se adapta solo a idiomas que no habías previsto. Elegir mal produce dos patologías reconocibles a simple vista. Base cero donde debía ir auto da esas barras de navegación donde el enlace de una palabra ocupa lo mismo que el de cuatro y el resultado parece una hoja de cálculo. Base auto donde debía ir cero da esas rejillas de tarjetas que nunca se alinean del todo porque un título de dos líneas ensancha su columna. Y lo peligroso es que la abreviatura flex: 1 toma la decisión por ti, en silencio, cada vez que la escribes sin pensar. La mayoría de los layouts flex torcidos que verás en tu carrera no tienen un bug: tienen una elección de base que nadie tomó conscientemente.