Flexbox
Lección 09 de 37 · 4 min
Flexbox acomoda elementos en una fila o en una columna, reparte el espacio que sobra y los alinea sin márgenes calculados a mano.
Ejes y dirección
Con display: flex un elemento pasa a ser un contenedor flex, y sus hijos directos, elementos flex. Los elementos se ordenan sobre el eje principal (main axis). El eje perpendicular a ese es el eje transversal (cross axis).
flex-direction elige el eje principal: row, el valor por defecto, lo pone horizontal, en el sentido del texto; column lo pone vertical, de arriba hacia abajo. gap agrega espacio entre los elementos, nunca contra los bordes del contenedor.
Mové los controles y mirá cómo la flecha del eje principal gira con flex-direction, y con ella lo que mueve cada propiedad de alineación. Las franjas rayadas cubren el espacio real entre los elementos: el gap, más lo que reparta justify-content.
.salida {display: flex;flex-direction: column;justify-content: space-between;align-items: stretch;gap: 8px;width: 256px;height: 192px;}
<div class="flex flex-col justify-between items-stretch gap-2 w-64 h-48"><div>08:42</div><div>Rosario</div><div>Andén 3</div></div>
Alineación
justify-content reparte el espacio libre sobre el eje principal, y align-items ubica los elementos en el eje transversal. Como siguen a los ejes, con column se intercambian: justify-content pasa a mover en vertical y align-items en horizontal.
- Agrupar
flex-start · center · flex-endAgrupan los elementos al inicio, en el centro o al final del eje. - Repartir
space-betweenPega el primero y el último a los bordes y reparte el resto del espacio entre ellos. - Rodear
space-aroundLe da a cada elemento el mismo espacio a cada lado, así que en los bordes queda la mitad que entre dos elementos. - Estirar
stretchEl valor por defecto dealign-items: estira los elementos para llenar el eje transversal, siempre que no tengan un tamaño fijo en ese eje.
align-self cambia la alineación transversal de un solo elemento. En el eje principal no hay equivalente (flexbox ignora justify-self), pero un margen automático hace el trabajo: margin-left: auto absorbe el espacio libre y empuja ese elemento, y los que lo siguen, hasta el final de la fila.
.barra {display: flex;align-items: center;gap: 8px;}.barra .salir {margin-left: auto; /* va al final de la fila */}
Cómo crecen los elementos
Cada elemento flex tiene tres propiedades de tamaño, todas sobre el eje principal:
- Base
flex-basisEl tamaño de partida. Por defectoauto, que toma su width o, si no tiene, su contenido. - Crecer
flex-growQué parte del espacio sobrante se lleva. Por defecto 0: no crece. - Ceder
flex-shrinkCuánto cede cuando falta lugar. Por defecto 1: todos ceden.
El reparto es proporcional. En un contenedor de 400px sin gap, con dos elementos de flex-basis 100px, sobran 200px; si sus flex-grow son 1 y 3, el primero recibe 50px y el segundo 150px, y terminan midiendo 150px y 250px.
El atajo flex: 1 equivale a flex: 1 1 0%: el elemento parte de cero y crece. Por eso varios elementos con flex: 1 quedan del mismo ancho mientras su contenido entre. En la demo, el destino se queda con todo el espacio libre: las franjas vuelven a medir solo el gap y justify-content ya no tiene nada que repartir.
.fila {display: flex;flex-wrap: wrap; /* lo que no entra baja de línea */gap: 16px;}.fila > * {flex: 1 1 200px;min-width: 0; /* deja que el texto se corte */}
Por defecto todo va en una sola línea (flex-wrap: nowrap); con wrap, los elementos que no entran pasan a la línea siguiente. Y un detalle que confunde: los elementos flex tienen min-width: auto, así que no se achican por debajo de su contenido más largo, como una URL. Para que un texto se corte con text-overflow: ellipsis, poné min-width: 0 en el elemento flex que lo contiene.
En Tailwind
En Tailwind, la clase flex es display: flex, no el atajo flex. Cada valor de alineación tiene su clase, y gap usa la misma escala de 4px que el relleno: gap-2 son 8px.
| CSS | Tailwind |
|---|---|
| display: flex · inline-flex | flex · inline-flex |
| flex-direction: row · column | flex-row · flex-col |
| justify-content: space-between | justify-between (start, center, around) |
| align-items · align-self: center | items-center · self-center |
| gap: 8px · margin-left: auto | gap-2 · ml-auto |
| flex: 1 · flex-shrink: 0 | flex-1 · shrink-0 · grow · basis-0 |
| flex-wrap: wrap · min-width: 0 | flex-wrap · min-w-0 |
<!-- barra: el logo a la izquierda, las acciones empujadas a la derecha --><nav class="flex items-center gap-4"><a href="/">Logo</a><a class="ml-auto" href="/ayuda">Ayuda</a><a href="/salir">Salir</a></nav><!-- columna en el teléfono, fila desde 48rem --><div class="flex flex-col gap-4 md:flex-row"><aside class="md:w-48 md:shrink-0">…</aside><main class="min-w-0 md:flex-1">…</main></div>
Flexbox
Lesson 09 of 37 · 4 min
Flexbox lays elements out in a row or a column, shares out the space that's left and aligns them, with no hand-tuned margins.
Axes and direction
With display: flex an element becomes a flex container, and its direct children become flex items. The items line up along the main axis. The axis perpendicular to it is the cross axis.
flex-direction picks the main axis: row, the default, makes it horizontal, in the direction of the text; column makes it vertical, top to bottom. gap adds space between the items, never against the container's edges.
Move the controls and watch the main axis arrow turn with flex-direction, and with it what each alignment property moves. The hatched bands cover the real space between the items: the gap, plus whatever justify-content shares out.
.departure {display: flex;flex-direction: column;justify-content: space-between;align-items: stretch;gap: 8px;width: 256px;height: 192px;}
<div class="flex flex-col justify-between items-stretch gap-2 w-64 h-48"><div>08:42</div><div>Albany</div><div>Track 3</div></div>
Alignment
justify-content shares out the free space along the main axis, and align-items places the items on the cross axis. Since they follow the axes, they swap with column: justify-content now moves things vertically and align-items horizontally.
- Pack
flex-start · center · flex-endPack the items at the start, the center or the end of the axis. - Spread
space-betweenPuts the first and last items against the edges and shares the rest of the space between them. - Surround
space-aroundGives each item the same space on each side, so the edges get half the space found between two items. - Stretch
stretchThe default foralign-items: stretches the items to fill the cross axis, as long as they have no fixed size on that axis.
align-self changes the cross axis alignment of a single item. There's no equivalent on the main axis (flexbox ignores justify-self), but an auto margin does the job: margin-left: auto soaks up the free space and pushes that item, and the ones after it, to the end of the row.
.bar {display: flex;align-items: center;gap: 8px;}.bar .sign-out {margin-left: auto; /* goes to the end of the row */}
How items grow
Each flex item has three sizing properties, all on the main axis:
- Basis
flex-basisThe starting size. It defaults toauto, which takes its width or, if it has none, its content. - Grow
flex-growWhat share of the leftover space it takes. It defaults to 0: it doesn't grow. - Shrink
flex-shrinkHow much it gives up when room runs out. It defaults to 1: they all give up some.
The split is proportional. In a 400px container with no gap and two items with a flex-basis of 100px, 200px are left over; if their flex-grow values are 1 and 3, the first gets 50px and the second 150px, so they end up 150px and 250px wide.
The shorthand flex: 1 means flex: 1 1 0%: the item starts from zero and grows. That's why several items with flex: 1 end up the same width, as long as their content fits. In the demo, the destination takes all the free space: the bands shrink back to the gap and justify-content has nothing left to share out.
.row {display: flex;flex-wrap: wrap; /* what doesn't fit moves to a new line */gap: 16px;}.row > * {flex: 1 1 200px;min-width: 0; /* lets the text get cut off */}
By default everything stays on one line (flex-wrap: nowrap); with wrap, items that don't fit move to the next line. And one detail that trips people up: flex items have min-width: auto, so they won't shrink below their longest piece of content, such as a URL. To cut text off with text-overflow: ellipsis, set min-width: 0 on the flex item that holds it.
In Tailwind
In Tailwind, the flex class is display: flex, not the flex shorthand. Each alignment value has its own class, and gap uses the same 4px scale as padding: gap-2 is 8px.
| CSS | Tailwind |
|---|---|
| display: flex · inline-flex | flex · inline-flex |
| flex-direction: row · column | flex-row · flex-col |
| justify-content: space-between | justify-between (start, center, around) |
| align-items · align-self: center | items-center · self-center |
| gap: 8px · margin-left: auto | gap-2 · ml-auto |
| flex: 1 · flex-shrink: 0 | flex-1 · shrink-0 · grow · basis-0 |
| flex-wrap: wrap · min-width: 0 | flex-wrap · min-w-0 |
<!-- bar: the logo on the left, the actions pushed to the right --><nav class="flex items-center gap-4"><a href="/">Logo</a><a class="ml-auto" href="/help">Help</a><a href="/sign-out">Sign out</a></nav><!-- a column on phones, a row from 48rem up --><div class="flex flex-col gap-4 md:flex-row"><aside class="md:w-48 md:shrink-0">…</aside><main class="min-w-0 md:flex-1">…</main></div>