Flexbox is the CSS layout mode for arranging items in one dimension: a row or a column. Tailwind gives each flexbox property a short class, so justify-center sets justify-content: center. Once you know which axis a class works on, the names are easy to predict.
Every demo on this page is live. Pick a class and the boxes move. The Tailwind panel shows the markup, and the CSS panel shows the CSS that Tailwind generates for it. Classes with a dotted underline are defaults that you can leave out. The green arrow is the main axis, and the orange arrow is the cross axis.
The examples use Tailwind CSS v4. The class names are the same in v3. In React, write className instead of class.
Turning an element into a flex container
Add flex to a parent element. The parent becomes a flex container, and its direct children become flex items. Grandchildren are not affected.
<div class="flex"> <div>A</div> <div>B</div> <div>C</div> <div>D</div></div>Tailwind
<div class="flex h-24">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
}Without any other class, three things happen:
- The items line up in a row, in source order, each as wide as its content.
- Each item stretches to the full height of the container.
- Items never wrap onto a second line. If they do not fit, they shrink.
inline-flex works the same way for the children, but the container itself flows inline with the surrounding text, like a button, instead of taking the full width.
Main axis and cross axis
Every flex container has two axes. The main axis is the direction in which the items are placed one after another. The cross axis runs at a right angle to it. flex-row and flex-col choose the main axis:
| Class | Main axis runs | Cross axis runs |
|---|---|---|
flex-row (default) |
Left to right | Top to bottom |
flex-row-reverse |
Right to left | Top to bottom |
flex-col |
Top to bottom | Left to right |
flex-col-reverse |
Bottom to top | Left to right |
Switch the direction and watch the arrows swap places:
Tailwind
<div class="flex flex-row h-44">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
flex-direction: row;
}This matters because the alignment classes are tied to the axes, not to the screen:
justify-*classes always work on the main axis.items-*,self-*, andcontent-*classes always work on the cross axis.
So justify-center centers horizontally in a row, but vertically in a column. When an alignment class seems to act in the wrong direction, check the direction first. For left-to-right languages, “start” is the left or top edge; in a right-to-left page, a row starts on the right.
Distributing items along the main axis
justify-* classes on the container decide where the free space on the main axis goes. Free space is whatever is left after the items take their size, so these classes only have a visible effect when the items do not fill the line.
Tailwind
<div class="flex flex-row justify-between h-48">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
}justify-start,justify-center, andjustify-endpack the items together at the start, the middle, or the end.justify-betweenputs the first item at the start and the last at the end, with equal space between the items and none at the edges.justify-aroundgives each item the same space on both sides. The gaps at the edges are half as wide as the gaps between items, because neighbors each contribute their own half.justify-evenlymakes every gap the same, including the two at the edges.
The column demo has a fixed height (h-48), so there is free space to distribute vertically. Without a height, a column is exactly as tall as its items, and justify-* has nothing to move.
Aligning items on the cross axis
items-* classes on the container position every item on the cross axis, within its line.
Tailwind
<div class="flex flex-row items-stretch h-52">
<div class="w-20 h-10">A</div>
<div class="w-20 h-16 text-2xl">B</div>
<div class="w-20 pt-6 text-sm">C</div>
<div class="w-20 h-12 text-3xl">D</div>
</div>CSS it generates
.container {
display: flex;
flex-direction: row;
align-items: stretch;
}items-stretchis the default. It makes an item fill the line on the cross axis, but only if the item has no fixed size in that direction. A, B, and D have a height (h-*), so they keep it; C has none and stretches.items-start,items-center, anditems-endplace the items at the start, middle, or end of the cross axis, at their own size.items-baselinealigns the items so that the first line of text in each one sits on the same baseline. Use it when items have different font sizes or padding, such as a large price next to a small label.
flex items-center is the most common Tailwind pair for vertical centering in a row: an icon next to text, or a button next to an input.
Gaps between items
gap-* puts space between neighboring items, but not at the outer edges of the container. gap-x-* and gap-y-* set the horizontal and vertical gaps separately, which matters once items wrap onto several lines.
Tailwind
<div class="flex flex-row gap-4">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
flex-direction: row;
gap: 1rem;
}Prefer gap-* over margins on the items, or over the older space-x-* utilities. A gap does not depend on which item comes first or last, and it still works when items wrap or are reordered.
Wrapping onto several lines
By default (flex-nowrap) all items stay on one line. If they are too wide, they shrink, and once they cannot shrink further they overflow the container. flex-wrap lets them break onto new lines instead.
Tailwind
<div class="flex flex-nowrap gap-2">
<div class="w-32">A</div>
<div class="w-32">B</div>
<div class="w-32">C</div>
<div class="w-32">D</div>
<div class="w-32">E</div>
<div class="w-32">F</div>
</div>CSS it generates
.container {
display: flex;
flex-wrap: nowrap;
gap: 0.5rem;
}Each item has w-32, but with flex-nowrap they all become narrower than that. In a flex container, a width is a starting point, not a promise. The section Growing and shrinking items explains how to stop an item from shrinking.
flex-wrap-reverse also reverses the cross axis, so the orange arrow points up. New lines are added above the first one, and items-start now means the bottom of each line.
Aligning the lines
When items wrap, the container holds several lines. content-* classes distribute those lines on the cross axis, the same way justify-* distributes items on the main axis. They need two things to have a visible effect: more than one line, and a container that is taller than its lines.
Tailwind
<div class="flex flex-wrap content-normal h-56">
<div class="w-36 h-10">A</div>
<div class="w-36 h-10">B</div>
<div class="w-36 h-10">C</div>
<div class="w-36 h-10">D</div>
<div class="w-36 h-10">E</div>
<div class="w-36 h-10">F</div>
</div>CSS it generates
.container {
display: flex;
flex-wrap: wrap;
align-content: normal;
}With content-normal, the default, the lines stretch to share the free space, and the items sit at the start of their stretched line. content-start, content-center, and content-end pack the lines together instead; content-between, content-around, and content-evenly spread them out exactly as their justify-* counterparts do.
The difference to items-* is the unit that moves: items-* positions items within their line, while content-* positions the lines within the container.
Aligning a single item
self-* on an item overrides the container’s items-* value for that item alone.
Tailwind
<div class="flex items-stretch h-36">
<div>A</div>
<div class="self-end">B</div>
<div>C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
align-items: stretch;
}
.item-b {
align-self: flex-end;
}self-auto is the default and means “use the container’s items-* value”. The other values match the items-* classes one to one.
There is no self-* for the main axis, because the items on a line share it. To push one item away from the others, give it an auto margin instead. ml-auto takes all the free space to the left of the item, as the navigation bar below shows.
Growing and shrinking items
The items so far have been as large as their content. The flex-*, grow, and shrink classes decide how items share the space on the main axis. They set the CSS flex shorthand, which combines three values:
- grow: how much of the free space the item takes, relative to the other items.
0means it does not grow. - shrink: how much the item gives up when there is not enough space.
0means it never gets smaller than its basis. - basis: the starting size before growing or shrinking.
automeans the item’s width or content size.
| Class | CSS | Use it for |
|---|---|---|
flex-initial (default) |
flex: 0 1 auto |
Content size, may shrink, does not grow |
flex-1 |
flex: 1 (same as 1 1 0%) |
Equal shares of the whole line, regardless of content |
flex-auto |
flex: 1 1 auto |
Content size plus an equal share of the free space |
flex-none |
flex: none |
Exactly its size; never grows or shrinks |
grow / grow-0 |
flex-grow: 1 / 0 |
Only change growing |
shrink / shrink-0 |
flex-shrink: 1 / 0 |
Only change shrinking |
basis-* |
flex-basis: … |
Set the starting size, such as basis-1/3 |
Select an item and change how it grows. Then narrow the container and see which items give way:
Tailwind
<div class="flex">
<div>Short</div>
<div class="flex-1">A much longer label</div>
<div>Medium text</div>
</div>CSS it generates
.container {
display: flex;
}
.item-b {
flex: 1;
}The two classes people mix up most are flex-1 and flex-auto. Both make items grow, but they start from a different size. flex-1 starts every item at zero, so all items end up the same width. flex-auto starts from each item’s content size, so longer content stays wider:
Tailwind
<div class="flex">
<div class="flex-1">Short</div>
<div class="flex-1">A much longer label</div>
<div class="flex-1">Medium text</div>
</div>CSS it generates
.container {
display: flex;
}
.item-a {
flex: 1;
}
.item-b {
flex: 1;
}
.item-c {
flex: 1;
}Tailwind
<div class="flex">
<div class="flex-auto">Short</div>
<div class="flex-auto">A much longer label</div>
<div class="flex-auto">Medium text</div>
</div>CSS it generates
.container {
display: flex;
}
.item-a {
flex: 1 1 auto;
}
.item-b {
flex: 1 1 auto;
}
.item-c {
flex: 1 1 auto;
}Changing the visual order
order-* moves an item without changing the HTML. Items are placed by ascending order value, and items with the same value keep their source order. Every item starts at 0, so order-first and order-last move an item before or after all the others.
Tailwind
<div class="flex">
<div>A</div>
<div>B</div>
<div class="order-first">C</div>
<div>D</div>
</div>CSS it generates
.container {
display: flex;
}
.item-c {
order: calc(-infinity);
}The *-reverse directions flip the whole sequence in the same way.
Common layouts
Most flexbox layouts in practice are a few combinations of the classes above.
Centering something
justify-center handles the main axis and items-center the cross axis, so together they center in both directions:
Tailwind
<div class="flex justify-center items-center h-40">
<div>Centered</div>
</div>CSS it generates
.container {
display: flex;
justify-content: center;
align-items: center;
}A navigation bar
The logo stays on the left and the links go to the right. The ml-auto on the first link takes all the free space on its left side, which pushes it and everything after it to the end:
Tailwind
<div class="flex items-center gap-4">
<div>Logo</div>
<div class="ml-auto">Home</div>
<div>Blog</div>
<div>About</div>
</div>CSS it generates
.container {
display: flex;
align-items: center;
gap: 1rem;
}
.item-home {
margin-left: auto;
}Header, content, and footer
A column where the main content grows keeps the footer at the bottom of the page, even when there is little content. On a real page, use min-h-screen on the container instead of a fixed height:
Tailwind
<div class="flex flex-col h-64">
<div>Header</div>
<div class="flex-1">Main</div>
<div>Footer</div>
</div>CSS it generates
.container {
display: flex;
flex-direction: column;
}
.item-main {
flex: 1;
}<body class="flex min-h-screen flex-col"> <header>…</header> <main class="flex-1">…</main> <footer>…</footer></body>An image next to text
The image keeps its size with shrink-0, and the text takes the rest of the line. items-start keeps the image at the top when the text runs over several lines:
Tailwind
<div class="flex items-start gap-4">
<div class="shrink-0 w-16 h-16">Image</div>
<div class="min-w-0 flex-1">A title and a description that is long enough to wrap onto a second line when the container gets narrow.</div>
</div>CSS it generates
.container {
display: flex;
align-items: flex-start;
gap: 1rem;
}
.item-image {
flex-shrink: 0;
}
.item-text {
min-width: 0;
flex: 1;
}A column on phones, a row on larger screens
Responsive variants switch any flex class at a breakpoint. Tailwind is mobile first, so the class without a prefix applies to small screens and md: takes over from 768 pixels:
<div class="flex flex-col gap-4 md:flex-row md:items-center"> <div>…</div> <div>…</div></div>Quick reference
All classes on this page, grouped by where they go:
| Goes on | Class | CSS property |
|---|---|---|
| Container | flex, inline-flex |
display |
| Container | flex-row, flex-row-reverse, flex-col, flex-col-reverse |
flex-direction |
| Container | flex-nowrap, flex-wrap, flex-wrap-reverse |
flex-wrap |
| Container | justify-start, -center, -end, -between, -around, -evenly |
justify-content |
| Container | items-stretch, -start, -center, -end, -baseline |
align-items |
| Container | content-normal, -start, -center, -end, -between, -around, -evenly, -stretch |
align-content |
| Container | gap-*, gap-x-*, gap-y-* |
gap, column-gap, row-gap |
| Item | self-auto, -start, -center, -end, -stretch, -baseline |
align-self |
| Item | flex-1, flex-auto, flex-initial, flex-none |
flex |
| Item | grow, grow-0, shrink, shrink-0, basis-* |
flex-grow, flex-shrink, flex-basis |
| Item | order-*, order-first, order-last, order-none |
order |
The same justify-*, items-*, content-*, and self-* classes also work in CSS Grid, where they mean slightly different things. The Alignment Cheatsheet for CSS and Tailwind lists every alignment utility next to the property it sets and the axis it moves.
Check your understanding
Question 1 of 10
0 of 10 checked