Stop Trying to Kill Flexbox: It’s Not a Grid Replacement

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:

CSS code on computer screen - CSS Transform Property: Four Common Uses / Blogs / Perficient
CSS code on computer screen – CSS Transform Property: Four Common Uses / Blogs / Perficient
.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.

Web developer coding - Web development, programmer engineering and coding website on ...
Web developer coding – Web development, programmer engineering and coding website on …

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

Web developer coding - Is Web Page Design Considered 'Coding'? - Get Me Coding
Web developer coding – Is Web Page Design Considered ‘Coding’? – Get Me Coding

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.

FAQ

When should I use Flexbox instead of CSS Grid?

Use Flexbox for one-dimensional, content-out layouts where the size of the content defines the layout. It excels at linear UI components like input groups (search bar + button), media objects, pagination controls, navigation bars, and rows of tags or chips. Reach for Grid when you need true two-dimensional structure with rows and columns that align simultaneously, like full page scaffolding.

Why won’t my flex item shrink below its content width with text-overflow ellipsis?

Flex items refuse to shrink below the size of their content by default, which breaks text truncation when you apply text-overflow: ellipsis. The fix is to add min-width: 0 to the flex child. It’s a feature, not a bug, but it feels like one. Keep this snippet handy because it comes up constantly with truncated text inside flex containers.

What does flex: 1 1 0 actually do compared to flex-grow: 1?

Using flex: 1 1 0 sets grow, shrink, and basis explicitly, giving you equal-width columns that respect the container space. If you only set flex-grow: 1 and leave basis as auto, a column with a long word becomes wider than a column with a short word. The shorthand forces you to acknowledge all three states instead of relying on browser defaults that surprise you.

How do I push a navbar element to the right without justify-content space-between?

Put margin-left: auto on the element you want pushed over, like a links container next to a logo. Inside a flex container, auto margins eat up all available empty space and shove the element to the side. This gives you more control than balancing space distribution on the parent with justify-content: space-between, especially when only one child needs to break away.

Your email address will not be published. Required fields are marked *

Zeen Social Icons