I was reviewing a pull request yesterday—around 4 PM, when my brain is usually checking out—and I saw something that made me physically wince. It was a full-page layout, sidebar and all, built entirely with display: flex, nested about six levels deep. The developer had used rigid percentages on flex-basis to force columns, negative margins to fake gutters, and media queries to manually break lines.
It worked, technically. But it was fragile as hell.
There seems to be this weird binary thinking floating around lately. Since CSS Grid got good (and by good, I mean widely supported enough that we stopped caring about IE years ago), a lot of folks decided Flexbox was “the old way.” Like it was a floppy disk or Flash player. They treat Grid as the upgrade to Flexbox.
It’s not. If you’re ditching Flexbox for everything, you’re making your life harder. But if you’re using it for page scaffolding, you’re making my life harder when I have to maintain your code.
The “String of Beads” Mental Model
Here’s the simplest way to think about it, and I wish someone had told me this back in 2015 when I was struggling to center a div. Flexbox is for one-dimensional layouts. It’s a string of beads.
You can layout that string horizontally (row) or vertically (column). You can squish the beads together or spread them apart. But it’s still just a line. Even when you use flex-wrap, it’s not really a grid; it’s just a line that broke onto a new row, like text wrapping in a paragraph. The rows don’t know about each other. A tall element in row one won’t align with anything in row two unless you force it with fixed widths, at which point, just use Grid.
Grid, on the other hand, is two-dimensional. It cares about rows and columns simultaneously. It’s a checkerboard.
I use Flexbox for the components inside the Grid cells. The navigation bar? Flexbox. The icon next to the text on a button? Flexbox. That card component where the footer needs to stick to the bottom? Flexbox (specifically flex-direction: column with margin-top: auto on the footer—works every time).
The flex Shorthand Trap
Here is where people mess up. I see this all the time:
.item {
flex-grow: 1;
}
And then they wonder why their items aren’t sizing the way they expect. The browser defaults matter here. If you just set grow, you’re ignoring shrink and basis. I’ve stopped writing the individual properties entirely. Just use the shorthand. It forces you to acknowledge all three states.
My go-to defaults usually look like this:
/* Grow evenly, shrink if needed, start from 0 size */
flex: 1 1 0;
/* Don't grow, don't shrink, stay at auto size */
flex: 0 0 auto;
That flex: 1 1 0 is magic for equal-width columns that actually respect the container space without content pushing them apart weirdly. If you leave the basis as auto (the default), a column with a long word in it will be wider than a column with a short word, even if they both have flex-grow: 1. That drove me nuts for months before I actually read the spec.
The min-width: 0 Gotcha
Speaking of things that drive me nuts: flex items won’t shrink below the size of their content by default. It’s a feature, not a bug, but it feels like a bug when your text truncation breaks.
If you have a flex item containing a text element with text-overflow: ellipsis, it often won’t truncate because the flex item refuses to shrink past the text width. The fix is stupidly simple: put min-width: 0 on the flex child. I have a snippet in VS Code just for this because I forget it at least once a week.
Alignment Magic (and confusion)
I still have to pause for a micro-second to remember the difference between justify-content and align-items. My brain hack? Justify follows the text flow (like justified text in Word). If your flex direction is row, justify works on the row (horizontal). If direction is column, justify works on the column (vertical).
Align is the “cross axis”—the one perpendicular to your flow.
But the real hero feature that doesn’t get enough love is margin: auto inside a flex container.
Back in the float days, we had to do math to push things apart. In Flexbox, if you have a navbar with a logo on the left and links on the right, you don’t need justify-content: space-between. You can just put margin-left: auto on the links container. It eats up all the available empty space and pushes the element to the side. It gives you way more control than trying to balance space distribution on the parent.
When I Actually Choose Flexbox
So, it’s 2026. We have Subgrid (finally working everywhere), we have container queries, we have all the toys. Why am I still writing display: flex?
1. Unknown content size
Flexbox is “content-out.” It excels when I want the layout to be defined by the size of the stuff inside it. If I have a row of tags or chips, I want them to be exactly as wide as the text inside them, plus padding. I don’t want to define a rigid column track for them.
2. Linear UI components
Input groups (search bar + button). Media objects (image + text block). Pagination controls. These are inherently linear. Using Grid here feels like using a sledgehammer to crack a nut. It works, but it’s verbose.
3. Vertical centering
Okay, place-items: center works in Grid too, and it’s shorter. But usually, when I’m centering something, I also need to control the relationship between children if there’s more than one. Flexbox handles that “flow” better.
The Gap Property
Can we take a moment to appreciate that gap works in Flexbox now? I remember the dark ages of using lobotomized owl selectors (* + * { margin-left: 1rem }) or negative margins on the container to handle spacing.
Now: gap: 1rem. Done. It works on rows and columns. It prevents that awkward margin on the last element. It’s clean. If you are still using margins to space out flex children, stop. Just stop. The support is there. It’s been there for years.
Don’t Over-Engineer It
The problem with that PR I reviewed wasn’t that Flexbox is bad. It’s that the dev was fighting the tool. They wanted a 2D grid structure but used a 1D tool to build it, which meant they had to write a ton of extra code to force the alignment.
If you find yourself calculating percentages (flex-basis: calc(33.333% - 20px)), you are working too hard. Switch to Grid.
But if you just need to line up a logo, a search bar, and a user avatar, and you want them to squish gracefully when the window shrinks? Flexbox is still the king. It’s not about which one is “better.” It’s about understanding the grain of the wood so you aren’t sanding against it.
Learn them both. But please, for the sake of my sanity during code reviews, stop trying to build full page layouts with flex-wrap.




