DEV Community

Leo
Leo

Posted on Originally published at news.html.to

flex-wrap: balance ends the wrapped-flex orphan

You have a row of tags. display: flex, flex-wrap: wrap, a modest gap. It works right up until a viewport width where five items become six, and that sixth item drops onto its own line, alone. The orphan.

That has been a "reach for a media query" moment for years. Chrome 150 ships a different answer: flex-wrap: balance.

The one keyword

The setup Ahmad Shadeed opens with in his walk-through is the classic wrapped flex row:

.list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}
Enter fullscreen mode Exit fullscreen mode

Swap wrap for balance, and the browser is now allowed to distribute items across the wrapped lines so a lone trailing item does not sit by itself:

.list {
  display: flex;
  flex-wrap: balance;
  justify-content: center;
  gap: 0.5rem;
}
Enter fullscreen mode Exit fullscreen mode

Same box model. Same track. What changes is which items land on which line: the layout algorithm balances the wrap.

What you used to write

Shadeed catalogs the workarounds this replaces, and the list is telling because each one is a hack:

  • max-width with a conditional clamp() on the flex items, tuned to force earlier wrapping at problem widths.
  • display: contents on a wrapping group so its children participate directly in the parent's flex line.
  • An extra, invisible flex item slipped into the middle of the list so the arithmetic works out.

Each ships fine. Each is also a load-bearing detail that has to be re-tuned whenever the content changes. flex-wrap: balance moves that judgment out of the stylesheet and into the browser.

flex-line-count, the companion

The article also demos flex-line-count, a property that asks for a minimum number of lines even when the items would happily fit on fewer:

.list {
  display: flex;
  flex-wrap: balance;
  flex-line-count: 2;
  gap: 0.5rem;
}
Enter fullscreen mode Exit fullscreen mode

Two lines, always, regardless of how much room the container has. That pairing is the interesting one. balance decides how many items sit on each line; flex-line-count decides how many lines exist in the first place. Together they get closer to the masonry-ish pattern people have been faking with grid for years, only with flex holding the reins.

Where support stands

flex-wrap: balance is in Chrome 150, Chrome only at the time Shadeed wrote the piece. No cross-browser Baseline. In production this is a progressive enhancement: browsers that do not recognize the value fall back to whatever flex-wrap computed to before, so you get today's slightly-off layout instead of a broken one.

Feature-detect it when the balanced result carries more weight than a polish pass:

@supports (flex-wrap: balance) {
  .list { flex-wrap: balance; }
}
Enter fullscreen mode Exit fullscreen mode

What to try on your next layout

Pick your worst offender. A primary nav. A tag cloud. A row of social icons. Anywhere the wrap point produces a stray element at some viewport width, drop flex-wrap: balance on the parent and see what the browser does with it. If the layout also wants a fixed row rhythm, layer flex-line-count and watch the two properties negotiate.

Grid has had the masonry conversation for a while, and subgrid has absorbed a lot of what wrap-heavy flex used to be forced into. flex-wrap: balance is a quieter move. Flex is not competing with grid here. It is finally holding its own contract without asking authors to backstop it with clamp().

Top comments (0)