Photo by PJH on Unsplash

On this page

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.

index.html
<div class="flex">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
main axis
cross axis
A
B
C
D

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;
}
With only the flex class, the items sit side by side and stretch to the container's height.

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:

Direction flex-direction
main axis
cross axis
A
B
C
D

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;
}
The direction decides which axis is horizontal. In a column, the items stretch across the width instead of the height.

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-*, and content-* 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.

Main axis justify-content
Direction flex-direction
main axis
cross axis
A
B
C
D

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-* moves the items along the main axis. Try justify-between, justify-around, and justify-evenly, then switch to flex-col.
  • justify-start, justify-center, and justify-end pack the items together at the start, the middle, or the end.
  • justify-between puts the first item at the start and the last at the end, with equal space between the items and none at the edges.
  • justify-around gives 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-evenly makes 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.

Cross axis align-items
Direction flex-direction
main axis
cross axis
A
B
C
D

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-* aligns all items on the cross axis. C has no height, so it only stretches with items-stretch. items-baseline lines up the first line of text.
  • items-stretch is 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, and items-end place the items at the start, middle, or end of the cross axis, at their own size.
  • items-baseline aligns 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.

Gap gap
Direction flex-direction
main axis
cross axis
A
B
C
D

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;
}
gap-* adds space between items only, in either direction.

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.

Wrapping flex-wrap
Gap gap
main axis
cross axis
A
B
C
D
E
F

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;
}
Narrow the container with the slider. With flex-nowrap the items shrink; with flex-wrap they move to a new line; flex-wrap-reverse stacks the new lines upward.

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.

Lines align-content
main axis
cross axis
A
B
C
D
E
F

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;
}
content-* moves whole lines. Each item has a fixed height, so the free space between the lines is visible.

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.

Cross axis align-items
Item click a box or pick it here
Own cross-axis alignment align-self
main axis
cross axis
A
B
C
D

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;
}
Select an item and give it its own self-* class. The container's items-* class still applies to the others.

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. 0 means it does not grow.
  • shrink: how much the item gives up when there is not enough space. 0 means it never gets smaller than its basis.
  • basis: the starting size before growing or shrinking. auto means 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:

Item click a box or pick it here
Grow and shrink flex
Shrink flex-shrink
main axis
cross axis
Short
A much longer label
Medium text

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;
}
B takes all the free space with flex-1. Give A flex-none or shrink-0 and it keeps its size when the container gets narrow.

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:

main axis
cross axis
Short
A much longer label
Medium text

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;
}
All three items have flex-1: equal widths.
main axis
cross axis
Short
A much longer label
Medium text

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;
}
All three items have flex-auto: the free space is shared equally, so the longer label stays wider.

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.

Item click a box or pick it here
Order order
main axis
cross axis
A
B
C
D

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);
}
Select an item and move it with order-first, order-last, or a number.

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:

main axis
cross axis
Centered

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;
}
flex justify-center items-center centers the child on both axes.

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:

main axis
cross axis
Logo
Home
Blog
About

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;
}
An auto margin absorbs the free space, so no justify-* class is needed.

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:

cross axis
main axis
Header
Main
Footer

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;
}
flex-col with flex-1 on the main element: the main area takes whatever height is left.
index.html
<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:

main axis
cross axis
Image
A title and a description that is long enough to wrap onto a second line when the container gets narrow.

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;
}
The image never shrinks; the text grows and is allowed to shrink thanks to min-w-0.

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:

index.html
<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

  1. 1. You add `flex` to a parent element and nothing else. What happens to its direct children?

Search articles

Type a word to search published articles.

Open the search page