Flexbox has been around for years, yet justify-content and align-items still trip people up regularly. It's not a memory problem — it's that the behavior of both properties changes depending on flex-direction, so memorizing "horizontal vs vertical" works until it suddenly doesn't.
This article builds from the concept of main axis and cross axis, explains why the confusion happens, and covers the most common layout patterns.
The Axes Are Not Fixed
A lot of people learn it as: "justify-content controls horizontal alignment, align-items controls vertical alignment." That's true with the default settings, but the moment flex-direction changes, it's wrong.
The accurate version:
justify-content: aligns along the main axisalign-items: aligns along the cross axis
The main axis is whatever direction flex-direction points:
flex-direction: row; /* main axis is horizontal (default) */
flex-direction: row-reverse; /* main axis is horizontal, right to left */
flex-direction: column; /* main axis is vertical */
flex-direction: column-reverse; /* main axis is vertical, bottom to top */
The cross axis is always perpendicular to the main axis. Horizontal main axis means vertical cross axis, and vice versa.
So when you switch to flex-direction: column, the two properties effectively swap roles:
/* flex-direction: row (default) */
.container {
display: flex;
justify-content: center; /* centers horizontally */
align-items: center; /* centers vertically */
}
/* flex-direction: column */
.container {
display: flex;
flex-direction: column;
justify-content: center; /* centers vertically! */
align-items: center; /* centers horizontally! */
}
The simplest way to remember it: justify follows the main axis, align follows the cross axis. Wherever the main axis points, that's what justify controls.
Vertical Centering Not Working?
This is the most common flexbox problem. You wrote align-items: center and nothing happened.
The cause is almost always the same: the container has no height, or not enough of one.
align-items positions elements along the cross axis, but if the container has no explicit height, its height collapses to the height of its content. There's no extra space for centering to happen.
/* Doesn't work: container height equals content height, no room to center */
.container {
display: flex;
align-items: center;
}
/* Works: give the container a height */
.container {
display: flex;
align-items: center;
height: 300px; /* or min-height, or 100vh */
}
Full-viewport vertical centering:
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
space-between vs space-around vs space-evenly
All three are justify-content values that distribute leftover space as gaps. The difference is how the space gets allocated:
space-between: |A B C| first and last items touch the edges; gaps are in between
space-around: | A B C | equal space on each side of every item (edge gaps = half of inner gaps)
space-evenly: | A B C | all gaps are exactly equal, including at the edges
In practice:
/* Nav bar: logo on left, links on right */
.nav {
display: flex;
justify-content: space-between;
}
/* Card grid: cards with even spacing throughout */
.cards {
display: flex;
justify-content: space-evenly;
}
That said, gap is generally the better tool for controlling spacing these days — it's more predictable, especially when items wrap:
.container {
display: flex;
flex-wrap: wrap;
gap: 16px; /* space between items only, not at the edges */
}
align-items vs align-content
Another common point of confusion.
align-items: controls how items align within each row on the cross axisalign-content: controls how multiple rows distribute themselves in the container — only has any effect whenflex-wrap: wrapis set and wrapping actually occurs
/* Single row: align-content does nothing */
.container {
display: flex;
align-items: center; /* works: controls alignment within the row */
align-content: center; /* no effect: only one row, nothing to distribute */
}
/* Multiple rows: both properties apply */
.container {
display: flex;
flex-wrap: wrap;
height: 400px;
align-items: flex-start; /* within each row: align to the top */
align-content: space-between; /* between rows: distribute evenly */
}
Memory hook: items handles what happens inside a row; content handles what happens between rows.
Common Layout Patterns
Center everything (the classic)
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
Nav bar: logo left, button right
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}
Push the last item to the far right
.nav {
display: flex;
align-items: center;
}
.nav .last-item {
margin-left: auto; /* auto margin consumes all remaining space */
}
Equal-height card grid
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: stretch; /* default — children stretch to match the tallest */
}
Vertical stack, horizontally centered
.container {
display: flex;
flex-direction: column;
align-items: center; /* with column direction, align-items controls horizontal */
}
To test any of these layouts directly, paste the HTML and CSS into the HTML Online Editor and see the result in real time. Changing one property and watching it update immediately is a lot faster than building a local test file.
Article URL:https://toolshu.com/en/article/justify-content-vs-align-items
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License 。



Loading...