Flexbox is the number-one star of CSS layout—and yet, every single time, you can’t remember which is which between justify-content and align-items. This article is a quick reference where you can look up every Flexbox property, each with a live demo. Press the demo buttons and check how each value works on the spot.
The big-picture map
Flexbox properties come in just two kinds: ones you put on the parent (the container) and ones you put on the child (the item).
| Where it goes | Property | Role |
|---|---|---|
| Parent | display: flex | The starting signal. Children line up horizontally |
| Parent | flex-direction | The direction to lay things out (horizontal / vertical) |
| Parent | justify-content | How to align along the direction things are laid out |
| Parent | align-items | How to align along the perpendicular direction |
| Parent | gap | The gaps between children |
| Parent | flex-wrap | Whether to wrap when things don’t fit |
| Child | flex | How to divide up leftover space |
| Child | align-self | Change only this one’s perpendicular alignment |
| Child | order | Change only this one’s position in the order |
Properties you put on the parent
display: flex—everything starts here
Just one line on the parent and the children line up in a horizontal row.
.container {
display: flex;
}justify-content—alignment along the direction things are laid out
For a horizontal row, “where along the horizontal direction to align.” Press the buttons and compare how the 6 values work.
| Value | How it works |
|---|---|
flex-start | Align to the start (default) |
center | Align to the center |
flex-end | Align to the end |
space-between | Stick to both ends, spacing evenly between |
space-around | Equal space on the left and right of each child |
space-evenly | Make all the gaps perfectly even |
align-items—alignment along the perpendicular direction
For a horizontal row, “where along the vertical direction to align.” How children of different heights get aligned is decided here.
| Value | How it works |
|---|---|
stretch | Stretch the height to fill the parent (default) |
flex-start | Align to the top |
center | Center vertically |
flex-end | Align to the bottom |
flex-direction—the direction to lay things out
.container {
flex-direction: row; /* lay out horizontally (default) */
flex-direction: column; /* lay out vertically */
flex-direction: row-reverse; /* horizontal, reverse order */
flex-direction: column-reverse; /* vertical, reverse order */
}Just note that with column, the directions handled by justify-content and align-items swap (justify becomes vertical, align becomes horizontal).
gap—the gaps between children
.container {
gap: 16px; /* 16px both vertically and horizontally */
gap: 8px 16px; /* 8px vertical, 16px horizontal */
}In the old days you’d space them one by one with margin, but now gap does it in one shot. It also has the advantage of not leaving extra space at the ends.
flex-wrap—wrapping
.container {
flex-wrap: nowrap; /* don't wrap (default). children get squished together */
flex-wrap: wrap; /* move to the next line when they don't fit */
}For things whose count changes, like a tag list or a card list, adding wrap gives peace of mind.
When wrapping produces two or more rows, what decides the alignment between the rows is a separate property called align-content (its values are the same lineup as justify-content). The usual reason it seems to do nothing is that flex-wrap is left at the default nowrap, so no wrapping ever happens—if you find yourself thinking “I wrote align-content but nothing changes,” first check whether the parent has flex-wrap: wrap.
Properties you put on the child
flex—how to divide up leftover space
The one you’ll use most is flex: 1. It means “take on the leftover space.”
.item {
flex: 1; /* give it to everyone for an even split */
}
.sidebar {
flex: 0 0 200px; /* don't grow, don't shrink, fixed width 200px */
}Three numbers in a row like flex: 0 0 200px is shorthand that writes the grow ratio, the shrink ratio, and the base width all at once.
| Position | Name | Meaning |
|---|---|---|
| 1st | flex-grow | How much it takes on the leftover to grow (0 = doesn’t grow) |
| 2nd | flex-shrink | How much it shrinks when space runs short (0 = doesn’t shrink) |
| 3rd | flex-basis | The base width for growing and shrinking |
So flex: 1 means “set the base width to 0, then take on the free space at a ratio of 1 and grow,” and flex: 0 0 200px means “neither grow nor shrink, and hold onto 200px.” Learn just these two patterns and you’ll cover almost everything in practice.
align-self—change only this one’s alignment
Override the parent’s align-items for just that child. You can do “everyone’s top-aligned, but only this one’s at the bottom.”
.item-special {
align-self: flex-end;
}order—change only this one’s position
Keep the HTML order as it is and change only the visual order. The smaller the number, the closer to the start (the default is 0).
.item-first {
order: -1; /* move to the start */
}6 recipes you can use as-is
Place dead center
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}A header with a logo on the left, menu on the right
.header {
display: flex;
justify-content: space-between;
align-items: center;
}Push just one item to the right end
.container {
display: flex;
}
.push-right {
margin-left: auto; /* auto for the left margin = pushed to the right end */
}A fixed-width sidebar plus a main area that takes the rest
.layout {
display: flex;
}
.sidebar {
flex: 0 0 200px;
}
.main {
flex: 1;
}A search form with a full-width input plus a button
.search {
display: flex;
gap: 8px;
}
.search input {
flex: 1; /* the input uses up all the leftover */
}A tag list that wraps as it lines up
.tags {
display: flex;
flex-wrap: wrap; /* move to the next line when they don't fit */
gap: 8px;
}A checklist for when Flexbox isn’t working
- They don’t line up at all →
display: flexgoes on the parent of the children you want to lay out. Did you write it on a child? - align-items doesn’t work → Without a height on the parent, there’s no room to align within. Check
heightormin-height - Children get squished → It’s because of
flex-wrap: nowrap(the default). Usewrapto wrap, andflex-shrink: 0for a child you don’t want squished - gap doesn’t work →
gapis a property you write on the parent (the flex container) side - justify-content doesn’t work → Are the children already filling the parent because of
flex: 1orwidth: 100%? With no leftover space, there’s nothing to align
Summary
- Properties come in just two kinds—ones on the parent and ones on the child. When in doubt, go to this article’s big-picture map
- justify is the direction things are laid out, align is the perpendicular direction—for a horizontal row, justify is horizontal and align is vertical
flex: 1means “take on the leftover”—give it to one for all of it, to everyone for an even split
You’ll pick up how the values work faster by playing with them than by reading about them. Press all the demo buttons above once, and next time you’ll write it without hesitation.