CSS Flexbox Made Simple: An Interactive Guide
11 min read
CSS Flexbox is a one-dimensional layout model for arranging items in rows or columns. It lets you build complex, responsive layouts without float or position. This guide covers every key property, each with an interactive example you can try.
You start using flexbox by adding display: flex to any container. Its children become flex items, and they line up along the main axis (more on that below).
css
.container {
display: flex;
}Switch between block, flex and inline-flex below. The block and flex containers stretch across the page, while the inline-flex container only takes the space its content needs and sits between the text either side of it.
display: block. Stacks the items, each on a line of its own
Direction and Axes
Flexbox has 2 axes: the main axis and the cross axis. Flex items line up along the main axis and stretch to fill the cross axis, and every property after this one works along one of them. The flex-direction property sets the direction of the main axis, and the cross axis always runs across it.
css
.container {
display: flex;
flex-direction: row;
}row-reverse and column-reverse only flip your flex items visually. Their order in the DOM stays the same, so screen readers and keyboard navigation still follow the original order, which can confuse people.
Change the flex-direction below and switch on Main axis or Cross axis to see where each one points.
flex-direction: row. Lays out the flex items side by side, left to right
Wrapping
Flex items try to fit onto one line by default. With enough items they spill out of their container, and flex-wrap lets them wrap onto new lines instead.
css
.container {
display: flex;
flex-wrap: nowrap;
}Drag the container width. With nowrap the items run out of the container (switch on Show overflow to see where they go); switch to wrap and they move onto new lines.
flex-wrap: nowrap. Keeps every flex item on one line
You can set direction and wrapping together with the flex-flow shorthand:
css
.container {
display: flex;
flex-flow: row wrap; /* flex-direction: row + flex-wrap: wrap */
}Gap Between Items
gap puts space between flex items without any margins. It only affects the direct children of the container, and it only adds space between items, never around the outside. row-gap and column-gap set each direction on its own, and gap: <row-gap> <column-gap> sets both.
css
.container {
display: flex;
gap: 1rem;
}Drag the gap slider, then switch on Row and column gaps and step flex-direction between row and column to see which one spaces the items.
gap: 0px. No gap: the flex items touch
Justify and Align
justify-content
justify-content positions your flex items along the main axis.
css
.container {
display: flex;
justify-content: flex-start;
}Step through the values and watch the measured gaps change.
justify-content: flex-start. Packs the flex items at the start of the main axis
align-items
align-items positions your flex items along the cross axis. It shares some values with justify-content and adds 2 of its own.
css
.container {
display: flex;
align-items: flex-start;
}Pick baseline to see items with different padding line up on their text.
align-items: flex-start. Lines the flex items up at the start of the cross axis
align-content
align-content spaces out the lines of a container that wraps. It takes the same values as justify-content, plus stretch, which is how it behaves by default. It does nothing when the container can’t wrap (flex-wrap: nowrap).
css
.container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}Step through the values and watch how the lines share the container’s height. With flex-wrap: wrap it works even when everything fits on one line; with nowrap it does nothing.
align-content: flex-start. Packs the lines at the start of the cross axis
align-self
align-self goes on a single flex item, not the container. It overrides align-items for that one item and takes the same values.
css
.flex-item-2 {
align-self: flex-start;
}Pick a box, then step through its align-self. Only that box moves.
align-self: auto. Follows the container's align-items, stretch here
Ordering
From here on, the properties go on the flex items rather than the container.
order changes the visual order of your flex items without touching the HTML. Every item has order: 0 by default, and items are laid out from the lowest value to the highest. Like the reverse values, it only changes what people see, so check keyboard and screen reader order after you use it.
css
.flex-item-1 {
order: 2;
}Pick a box, then change its order. Each box keeps its own value, so try moving the last one to the front with -1.
order: 0. Flex item 3 has the default order, so it keeps its place in the HTML
Growing and Shrinking
Flex items can grow to fill extra space or shrink when space is tight. You control this with flex-grow, flex-shrink and flex-basis.
flex-basis
flex-basis sets an item’s starting size, before any growing or shrinking. The default is auto, and you can also use fixed units (px, em, rem), percentages or content-based values. It acts like width in a row and like height in a column.
css
.flex-item-1 {
flex-basis: 150px;
}flex-grow
flex-grow decides how much of the leftover space an item takes. The default is 0, so items stay at their starting size. Give an item a positive number and it grows into the extra space, compared with its siblings.
css
.flex-item-1 {
flex-grow: 2; /* takes twice as much of the extra space as an item with flex-grow: 1 */
}flex-shrink
flex-shrink decides how much an item shrinks when the container is too small. The default is 1, so items shrink as needed. A higher number makes an item give up more space than its siblings, and 0 stops it shrinking at all. Shrinking also scales with size, so when 2 items both have flex-shrink: 1, the bigger one gives up more space in pixels.
css
.flex-item-1 {
flex-shrink: 0; /* never shrinks below its flex-basis */
}Putting Them Together
Pick a box and change its flex-grow, flex-shrink and flex-basis. Small bases leave space to grow into; make them bigger than the container and the boxes shrink.
flex: 1 1 100px. Flex item 1 takes 1 share of any extra space and shrinks when space runs out
The flex shorthand sets all 3 at once:
css
.flex-item-1 {
flex: 1 0 200px; /* grow, shrink, basis */
}Common Patterns
Centering a Div
To center a div, set justify-content and align-items to center on its container. justify-content centers it on the main axis and align-items centers it on the cross axis. The container needs to be taller than the div for the vertical centering to show.
css
.container {
display: flex;
justify-content: center;
align-items: center;
}Step each one to center to see which direction it centers.
centering: not centered. Both at flex-start: the item sits in the top-left corner
A Responsive Grid Without Media Queries
Flexbox can build a responsive grid without any media queries. Each item starts at 100px and grows to share the extra space on its row. With flex-wrap: wrap, an item moves onto a new row when there isn’t room for it at 100px, so the number of columns follows the container’s width, which works well for card layouts.
css
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1 1 100px;
}Drag the container width or add items, and watch them wrap onto new rows.
Browser Support
Flexbox
BaselineWidely availableSupported in Chrome: yes.
Supported in Edge: yes.
Supported in Firefox: yes.
Supported in Safari: yes.
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015
What’s Next
That covers the flexbox properties you’ll use for most layouts. If you want more guides like this, the videos are on YouTube.