Menu

CSS Flexbox: display flex, Axes, Alignment and flex

Flexbox lays items out in a row or a column and controls how they share space and line up. Learn display: flex, the main and cross axis, every container property, flex-grow, flex-shrink and flex-basis, with a live playground that measures where each item lands.

This page includes runnable editors - edit, run, and see output instantly.

What display: flex does

Put display: flex on a parent and its direct children line up in a row, side by side, and stretch to the same height. That one declaration replaces floats, inline-block and most positioning tricks for laying out a row of things.

In the first box each div takes a full line. In the second the three items sit in one row, each only as wide as its content, and One and Three stretch to the height of Two. Only the parent changed: display: flex goes on the container, never on the items.

Flexbox playground

Pick values and watch the items move. The code line under the box is the CSS for what you see, and the list under it is where the browser actually placed each item, measured with getBoundingClientRect().

Things to try:

  • justify-content: space-between: item 1 lands at x 0 and item 3 touches the far edge.
  • align-items: center: the three items keep their own heights and their centers line up. With the default stretch, item 1 has no height of its own and fills the container's full 170px.
  • flex-direction: column: now justify-content moves items vertically and align-items horizontally. The two properties follow the axes, not the screen.

Main axis and cross axis

Every flex container has two axes. The main axis is the direction the items flow in, set by flex-direction. The cross axis runs across it.

flex-directionMain axisCross axisjustify-content moves itemsalign-items moves items
row (default)horizontal, in reading orderverticalhorizontallyvertically
row-reversehorizontal, reversedverticalhorizontallyvertically
columnvertical, top to bottomhorizontalverticallyhorizontally
column-reversevertical, bottom to tophorizontalverticallyhorizontally

In a right to left page (dir="rtl"), row starts at the right edge, because the main axis follows the writing direction.

Container properties

These go on the element with display: flex:

PropertyWhat it doesDefault
flex-directionRow or column, and which wayrow
flex-wrapWhether items move to a new line when they run out of roomnowrap
flex-flowShorthand for flex-direction and flex-wraprow nowrap
justify-contentPlacement and spacing along the main axisnormal (acts as flex-start)
align-itemsPlacement of items along the cross axisnormal (acts as stretch)
align-contentSpacing between lines when items wrapnormal
gapSpace between items (row-gap, column-gap)0

justify-content and align-items each have their own page with every value: justify-content and align-items. Wrapping and direction are on the flex-wrap page.

Item properties: flex-grow, flex-shrink, flex-basis

These go on the children and decide how they share the container's width:

  • flex-basis: the size an item starts from before free space is shared out (auto means "use my width or my content").
  • flex-grow: how many shares of the leftover space the item takes. 0 means it never grows.
  • flex-shrink: how much the item gives up when there is not enough space. 0 means it never shrinks.

The flex shorthand sets all three:

You writeWhich meansBehavior
flex: initial (default)0 1 autoContent size, may shrink, never grows
flex: 11 1 0%Starts from zero and takes an equal share of the space
flex: auto1 1 autoContent size plus a share of the leftover space
flex: none0 0 autoExactly its content or width, never grows or shrinks
flex: 22 1 0%Twice the share of an item with flex: 1

Each row is 480px wide inside its padding, and the two 8px gaps leave 464px for the items. The printed widths show how it was shared: about 155px each in the first row, 116 + 232 + 116 in the second (the flex: 2 item gets twice the share of each neighbor), and 100 + 372 in the third, where the flex: none item keeps its width and the other item takes all the rest.

Real layouts with flexbox

A header with a logo at the start and links at the end is the most common flex layout. margin-inline-start: auto on one item eats all the free space before it and pushes it and everything after it to the end:

align-items: center lines up the bigger logo text with the links, and gap spaces the links without margins to undo on the last one.

A second everyday pattern is a media row: a fixed-size icon and text that takes the rest and wraps inside its own column.

flex: none is the guarantee. Flex items shrink by default, so if you remove it from the circle and also remove flex: 1 from the text, the paragraph squeezes the circle to about 23px wide: an oval. To center one thing in a box, flexbox is two lines (justify-content: center; align-items: center); the center a div page compares that with the other ways.

order and accessibility

The order property and the -reverse directions change where items appear, not where they are in the HTML. Screen readers and the Tab key still follow the HTML order, so a keyboard user can jump from the first link on screen to the last one. Use them for decoration only; when the order means something, change the HTML.

Flexbox or grid

Flexbox works in one direction at a time: items in a row size themselves from their content, and a second line (with wrapping) does not line up with the first. Grid works in two: you define columns and rows and items snap into them. A nav bar, a toolbar or a form row is flexbox; a gallery or a page with a sidebar is grid.

Common mistakes

  • display: flex on the item instead of the parent. The container gets display: flex; its children are the items.
  • Expecting align-items to move items vertically with no height. If the container is only as tall as its tallest item, there is no room to move. Give the container a height, or it is working and just has nothing to do.
  • Text that overflows instead of shrinking. Flex items have min-width: auto. Add min-width: 0 to the item that should shrink.
  • Using flex: 1 and wondering why widths differ. Items with flex: 1 share space equally, but an item whose content cannot fit (a long URL, an image) will not shrink below it. min-width: 0 fixes that too.
  • Margins between items. Use gap on the container; it only goes between items.
  • Nesting flex needlessly. Only direct children are flex items. Grandchildren follow normal layout unless their own parent is also display: flex.

Frequently Asked Questions

What does display: flex do?

It turns an element into a flex container. Its direct children become flex items and are placed in a row by default, side by side, stretched to the same height, with properties like justify-content, align-items and gap controlling how they share the space.

What does flex: 1 mean?

flex: 1 is short for flex: 1 1 0%: the item may grow (flex-grow: 1), may shrink (flex-shrink: 1), and starts from a size of zero (flex-basis: 0%). Items that all have flex: 1 split the free space equally, so they end up the same width unless their content cannot fit.

What is the difference between justify-content and align-items?

justify-content places items along the main axis (horizontally in a row), and align-items places them along the cross axis (vertically in a row). With flex-direction: column the two axes swap, so justify-content becomes vertical.

Should I use flexbox or grid?

Use flexbox for a single row or column whose items size themselves from their content: nav bars, button groups, a label next to an input. Use grid when you want rows and columns that line up with each other, such as a card grid or a page layout.

Why does my flex item overflow its container?

A flex item has min-width: auto by default, so it refuses to shrink below the width of its longest word or widest child. Set min-width: 0 (or overflow: hidden) on the item to let it shrink, for example to make text-overflow: ellipsis work.

Does flexbox work on inline elements like span?

Yes. Any element with display: flex is a flex container, and its children become flex items whatever their own display value, so <span> children stop being inline and accept width, height and margin like blocks.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED