Understanding Flexbox: Aligning and Distributing Items Easily


"This guide makes CSS Flexbox easy to understand. We’ll walk you through how the parent container and its child items work, and show you all the cool
Flexbox (short for Flexible Box) is a layout model introduced to make it easier to space, align, and arrange items inside a container—even when their sizes are unknown or change dynamically (hence, “flex”).
The core idea is to let the container adjust the size, order, and spacing of its child elements to make the best use of space. Whether you're working with big screens or small mobile devices, Flexbox helps everything fit just right by growing or shrinking items as needed.
What makes Flexbox extra cool is that it's direction-neutral. Unlike the traditional block (vertical) or inline (horizontal) layouts, Flexbox can flow in any direction, making it super handy for responsive design and complex layouts that need to stretch or shift around.
💡 Quick Tip: Flexbox is best for smaller, component-level layouts. For full-page or large-scale designs, CSS Grid is usually the better pick.
Basics and terminology
Since Flexbox is a full layout system—not just a single CSS property—it comes with a bunch of features. Some properties are used on the parent (called the "flex container") and others go on the children (called "flex items").
Unlike regular layouts that follow block (vertical) or inline (horizontal) directions, Flexbox follows something called “flex-flow directions.” To get a better grip on it, imagine this:
There are two main directions in Flexbox:
Main Axis: This is the direction your flex items flow in—either left to right, top to bottom, etc.—based on the
flex-direction
you set.Cross Axis: This is the direction across the main axis. So if your main axis is horizontal, the cross axis is vertical (and vice versa).
Here are a few key terms to know:
Main Start / Main End: Where the items start and finish along the main axis.
Main Size: The width or height of a flex item in the main direction.
Cross Start / Cross End: Where the items begin and end on the cross axis.
Cross Size: The size of a flex item in the cross direction.
Basically, Flexbox lets you control both directions easily, so your layout adapts nicely—no matter the screen size or orientation.
Flexbox properties
Properties for the Parent (flex container)
Display
This is the first step to using Flexbox. When you set
display: flex
ordisplay: inline-flex
on a container, it becomes a flex container. That means all of its direct children turn into flex items and follow flexbox rules.
.container {
display: flex; /* or inline-flex */
}
👉 Just a heads-up: CSS columns don’t work inside a flex container—so you can’t mix both.
flex-direction
This sets the main axis, which means it decides the direction your flex items will line up in. Flexbox is a one-direction layout—items go in a row or a column, not both at once.
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
Here’s what each option does:
row
(default): Items go left to right (or right to left if using RTL text).row-reverse
: Items go in the opposite direction—right to left in LTR mode.column
: Items stack top to bottom.column-reverse
: Items stack bottom to top.
- flex-wrap
By default, flex items will all try to fit onto one line. You can change that and allow the items to wrap as needed with this property.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
nowrap
(default): all flex items will be on one linewrap
: flex items will wrap onto multiple lines, from top to bottom.wrap-reverse
: flex items will wrap onto multiple lines from bottom to top.
flex-flow
This is just a shortcut for writing both
flex-direction
andflex-wrap
in one line. It sets how items flow along the main and cross axes.
.container {
flex-flow: column wrap;
}
In this example:
column
sets the main axis (top to bottom),wrap
allows items to move to the next line if needed.
📝 Default is: row nowrap
— items go left to right and don’t wrap.
- justify-content
This controls how items are spaced along the main axis (like left to right in a row, or top to bottom in a column). It’s useful when there’s extra space left over, or when items overflow a line.
.container {
justify-content:
flex-start | flex-end | center | space-between |
space-around | space-evenly | start | end | left | right
[+ safe | unsafe];
}
Here’s what each option does:
flex-start
(default): Items stick to the start of the main axis.flex-end
: Items stick to the end.center
: Items are centered.space-between
: First item goes to the start, last to the end, and the rest spread out evenly in between.space-around
: Items have equal space around them. (Edges get half-space compared to between items.)space-evenly
: Equal space between all items and container edges.start
/end
: Based on writing direction (like top-to-bottom languages).left
/right
: Aligns items to left or right—if it makes sense with your layout direction.
- align-items
This controls how flex items line up along the cross axis (the direction perpendicular to the main axis). Think of it like justify-content
, but for the other direction.
.container {
align-items:
stretch | flex-start | flex-end | center | baseline |
first baseline | last baseline | start | end | self-start | self-end
[+ safe | unsafe];
}
What these mean:
stretch
(default): Items stretch to fill the container’s cross axis (but still respect min/max size).flex-start
/start
/self-start
: Items align to the start of the cross axis. The differences are small and relate to layout or writing mode rules.flex-end
/end
/self-end
: Items align to the end of the cross axis, again with subtle differences based on direction rules.center
: Items are centered along the cross axis.baseline
: Items line up by their text baselines.
align-content
This controls how lines of flex items are spaced along the cross axis when there’s extra space—kind of like how justify-content
works for items on the main axis.
Note: It only works when your flex container allows wrapping (
flex-wrap: wrap
orwrap-reverse
). If you have a single line (nowrap
), this property won’t do anything.
.container {
align-content:
flex-start | flex-end | center | space-between |
space-around | space-evenly | stretch | start | end |
baseline | first baseline | last baseline
[+ safe | unsafe];
}
How the values behave:
normal
(default): Lines stay where they are, no extra spacing.flex-start
/start
: Lines packed toward the start.flex-end
/end
: Lines packed toward the end.center
: Lines centered in the container.space-between
: Lines spread out evenly, first line at the start, last at the end.space-around
: Equal space around each line.space-evenly
: Equal space between lines and container edges.stretch
: Lines stretch to fill leftover space.
You can add safe
or unsafe
to avoid pushing content off-screen, but support isn’t perfect yet.
gap, row-gap, column-gap
The gap
property explicitly controls the space between flex items. It applies that spacing only between items not on the outer edges.
.container {
display: flex;
...
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px;
column-gap: 20px;
}
The behavior could be thought of as a minimum gutter, as if the gutter is bigger somehow (because of something like justify-content: space-between;
) then the gap will only take effect if that space would end up smaller.
It is not exclusively for flexbox, gap
works in grid and multi-column layout as well.
Properties for the Children (flex items)
order
By default, flex items show up in the order they appear in your HTML. But with order
, you can change how they’re arranged inside the flex container.
.item {
order: 5; /* default is 0 */
}
Items with a lower order number show up first. If multiple items have the same order, they go back to their original order in the code.
flex-grow
This controls how much a flex item should grow to fill extra space in the container. It takes a number (no units) that works like a ratio.
.item { flex-grow: 4; /* default is 0 */ }
If every item has
flex-grow: 1
, they share leftover space equally. If one item hasflex-grow: 2
, it tries to take twice as much space as the others.flex-shrink
This defines the ability for a flex item to shrink if necessary.
.item { flex-shrink: 3; /* default 1 */ }
Negative numbers are invalid.
flex-basis
This sets the starting size of a flex item before the leftover space is shared out. You can use a fixed length (like
100px
,20%
, etc.) or a keyword..item { flex-basis: 0 | auto; /* default is auto */ }
auto
(default): Uses the item’swidth
orheight
(depending on flex direction).0
: Ignores the item’s content size and letsflex-grow
fully control sizing.
There’s also a content
keyword, but it's not widely supported yet, so it’s tricky to use reliably.
📌 Use flex-basis
when you want more control over how big items start before Flexbox kicks in.
flex
This is a shortcut to set
flex-grow
,flex-shrink
, andflex-basis
all in one go..item { flex: none | [flex-grow flex-shrink? flex-basis?]; }
💡 Example:
.item { flex: 5; } /* Means: flex-grow: 5; flex-shrink: 1; flex-basis: 0%; */
If you just use a number, it assumes
flex-basis
is0%
.Default is:
flex: 0 1 auto
.
align-self
This lets you override the
align-items
setting for a single flex item. So if most items are aligned one way, but you want one item to stand out—this is your tool..item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }
auto
(default): Follows the value fromalign-items
.Others work just like in
align-items
.
📌 Also, things like float
, clear
, and vertical-align
don’t affect flex items—so stick to Flexbox properties here.
Subscribe to my newsletter
Read articles from Hari Rajak directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
