When you lay out cards with justify-content: space-between, the items on the final row spread to opposite edges and the grid stops looking like a grid. This article covers how to pull the last item back to the left.
The short answer: stop using space-between and use gap instead. The pseudo-element trick that is usually recommended breaks depending on how many items you have.
▼Three approaches
| Approach | Reliability | Best for |
|---|---|---|
gap with flex-start |
Always works | New code |
margin-right: auto on the last item |
Only with one item left over | Single-row layouts |
| Filling with a pseudo-element | Depends on the item count | Supporting older browsers |
Sponsored
Why the last item does not move left
space-between means “push to both edges and distribute the leftover space between the items”. If the final row holds two items, one goes hard left and the other hard right.
Say you are laying out seven cards in three columns. The final row holds one card, which sits on the left as expected. Change it to eight cards and the final row holds two, which separate to opposite ends. That is the misalignment people are trying to fix.
What you actually want is for items to pack from the left regardless of how many there are.
Using gap (recommended)
Set justify-content: flex-start and create the spacing with gap. Items then pack from the left no matter how many there are.
<div class="flex-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.flex-container {
display: flex;
flex-wrap: wrap;
/* pack from the left instead of spreading */
justify-content: flex-start;
gap: 20px;
}
.item {
/* three columns, minus the gaps */
width: calc((100% - 40px) / 3);
}
Three columns means two gaps, so subtract 40px from the width calculation. The final row never misbehaves because nothing is being spread.
If the column count should change with the viewport, Grid is simpler:
.flex-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
auto-fill adjusts the column count automatically and removes the need for calc(). For laying out cards, Grid expresses the intent more directly than Flexbox.
Sponsored
margin-right: auto on the last item
Put margin-right: auto on the last item, not on the container. On the container it does nothing to the children.
An auto margin absorbs leftover space. Placing one to the right of the final item collects the slack there and pushes the item left.
.flex-container {
display: flex;
justify-content: space-between;
}
/* on the last child, not the container */
.flex-container > *:last-child {
margin-right: auto;
}
Writing margin-right: auto on the container changes nothing about how the children sit. That declaration positions the container itself within its own parent.
This approach also only works on a single row. With flex-wrap: wrap, :last-child is the last item of the final row, so the space lands in the wrong place on other rows.
Filling the gap with a pseudo-element
Adding a dummy element to pad out the final row. It does not work for every item count.
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.flex-container::after {
content: "";
flex: 1;
}
You only get one ::after, so this fixes a final row with one item left over, and does nothing for a row with two. In a three-column layout it works when the item count divides by three with a remainder of one.
For a list whose length varies, this is not dependable. Unless the item count is fixed, use the gap approach.
Which to choose
For new code, gap every time. space-between is for when you genuinely want items pushed to both edges, not for left-aligned grids.
Laying items out with space-between and then patching the last row is the long way round. Align to the start and create the spacing with gap: shorter, and nothing to break.
The CSS gap property for Flexbox and Grid spacing covers the property in more depth, including setting row and column spacing separately.
For layout patterns handled by the framework instead, see recent CSS Grid updates and how to apply them.