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 defaultstretch, item 1 has no height of its own and fills the container's full 170px.flex-direction: column: nowjustify-contentmoves items vertically andalign-itemshorizontally. 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-direction | Main axis | Cross axis | justify-content moves items | align-items moves items |
|---|---|---|---|---|
row (default) | horizontal, in reading order | vertical | horizontally | vertically |
row-reverse | horizontal, reversed | vertical | horizontally | vertically |
column | vertical, top to bottom | horizontal | vertically | horizontally |
column-reverse | vertical, bottom to top | horizontal | vertically | horizontally |
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:
| Property | What it does | Default |
|---|---|---|
flex-direction | Row or column, and which way | row |
flex-wrap | Whether items move to a new line when they run out of room | nowrap |
flex-flow | Shorthand for flex-direction and flex-wrap | row nowrap |
justify-content | Placement and spacing along the main axis | normal (acts as flex-start) |
align-items | Placement of items along the cross axis | normal (acts as stretch) |
align-content | Spacing between lines when items wrap | normal |
gap | Space 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 (automeans "use my width or my content").flex-grow: how many shares of the leftover space the item takes.0means it never grows.flex-shrink: how much the item gives up when there is not enough space.0means it never shrinks.
The flex shorthand sets all three:
| You write | Which means | Behavior |
|---|---|---|
flex: initial (default) | 0 1 auto | Content size, may shrink, never grows |
flex: 1 | 1 1 0% | Starts from zero and takes an equal share of the space |
flex: auto | 1 1 auto | Content size plus a share of the leftover space |
flex: none | 0 0 auto | Exactly its content or width, never grows or shrinks |
flex: 2 | 2 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: flexon the item instead of the parent. The container getsdisplay: flex; its children are the items.- Expecting
align-itemsto 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. Addmin-width: 0to the item that should shrink. - Using
flex: 1and wondering why widths differ. Items withflex: 1share space equally, but an item whose content cannot fit (a long URL, an image) will not shrink below it.min-width: 0fixes that too. - Margins between items. Use
gapon 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.