A three-card layout looks great at tablet width—until someone opens the same page on a 1440 px ultrawide monitor, and the cards stretch wall to wall with zero visible spacing. The root cause lies in how the Flexbox algorithm prioritizes flex-grow over justify-content.
Table of Contents
The Wide-Screen Spacing Mystery
A three-card layout looks great at tablet width. The cards sit neatly across the row, with comfortable gaps courtesy of justify-content: space-between. Then someone opens the same page on a 1440 px ultrawide monitor, and the cards stretch wall to wall with zero visible spacing. The flexbox space-between not working on wide screens problem is a frequent layout frustration, and it is almost never a browser bug.
The root cause lies in how the Flexbox algorithm prioritizes flex-grow over justify-content. When growing items consume every last pixel of available space, justify-content has nothing left to distribute. This guide walks through the spec rule that governs this behavior, provides a three-step diagnostic checklist, presents four code-level fixes (one of which is a visual mitigation rather than a true gap restoration), and offers a CSS Grid alternative that sidesteps the problem entirely.
How justify-content Actually Works Under the Hood
Positive Free Space on the Main Axis
The Flexbox specification defines “positive free space” as the container’s main size minus the sum of all flex items’ hypothetical main sizes. Put concretely: if a flex container is 1200 px wide and it holds three items whose base sizes total 900 px, there are 300 px of positive free space. The justify-content property exists solely to distribute this leftover space. With space-between, those 300 px would be split into two equal 150 px gaps placed between adjacent items.
MDN’s documentation on justify-content () states this explicitly: when flex items have a flex-grow factor greater than 0, there is no free space remaining, so justify-content has no visible effect. That single sentence explains the vast majority of “justify-content space-between no effect” bug reports.
Why flex-grow Trumps justify-content
The Flexbox sizing algorithm executes in a strict order. First, it resolves the flex base sizes of each item (from flex-basis, width, or intrinsic content size). Second, it distributes positive free space according to each item’s flex-grow factor, or reclaims negative free space via flex-shrink. Only after those steps does justify-content act on whatever free space remains. If flex-grow consumes all free space, the amount handed to justify-content is exactly zero, regardless of whether the value is space-between, space-around, or space-evenly. The result: no effect.
This is the broken state in practice:
<div class="container">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
</div>
.container {
display: flex;
justify-content: space-between;
}
.card {
flex: 1 1 0%;
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
With flex: 1 1 0%, each card’s flex base size is 0%, and the flex-grow factor of 1 causes all three items to divide the container’s entire width equally. No pixel is left over. justify-content: space-between receives zero distributable space and produces zero gaps.
The 3-Step Diagnostic Checklist
Before reaching for a fix, confirm the diagnosis. This checklist can be bookmarked or screenshotted for quick reference during flexbox debugging sessions.
Step 1: Inspect Free Space
Open browser DevTools, select the flex container, and activate the Flexbox overlay (in Chrome, click the flex badge next to the element in the Elements panel; in Firefox, enable the Flexbox overlay in the Layout panel; in Safari, use the Flexbox badge in the Elements inspector). If the overlay shows items filling 100% of the main axis with no highlighted free-space regions, free space equals zero. That confirms justify-content has nothing to work with.
Step 2: Check flex-grow Values
The most common culprit is the shorthand flex: 1, which browsers expand to flex: 1 1 0% (equivalent to flex: 1 1 0px; the unitless 0 is valid as flex-basis in the flex shorthand per the CSS Flexbox spec). Select each flex item in DevTools and examine its computed flex-grow value in the Computed panel. Any value greater than 0 on every item means every item absorbs all positive free space before justify-content runs. Developers apply this shorthand for equal-width columns without realizing it neutralizes justify-content entirely.
Step 3: Verify Container Constraints
Confirm that the flex container itself is bounded. If the container has no max-width and sits inside a full-viewport wrapper, its main size grows with the viewport. Wider viewport means more free space, but flex-grow items simply expand further to consume it. The gap never materializes because the ratio of consumed space to total space remains 100% at every breakpoint.
Four Ways to Restore space-between on Wide Screens
Fix 1: Remove or Zero-Out flex-grow
The most direct CSS flexbox troubleshooting fix is to stop items from growing. Setting flex: 0 1 auto tells items to use their intrinsic or explicitly declared width and leave the remaining space untouched, while still allowing them to shrink if the container is too narrow. Note: flex: none expands to 0 0 auto, which disables shrinking as well. Use flex: none only if items should never shrink below their base size. That remaining space becomes distributable, and justify-content: space-between can place it between items.
.container {
display: flex;
justify-content: space-between;
}
.card {
flex: 0 1 300px;
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
On a 1200 px container with three 300 px cards, there are 300 px of free space. space-between places 150 px between card 1 and card 2, and another 150 px between card 2 and card 3. The flex shorthand and justify-content: space-between interact as expected because no growth is occurring.
Fix 2: Constrain Items with max-width
Sometimes items do need to grow, just not without limit. Keeping flex-grow: 1 but adding a max-width to each item creates a ceiling. Once an item reaches its maximum size, it stops growing. justify-content distributes whatever free space the items leave behind. For edge cases involving minimum and maximum size clamping, the CSS Flexbox specification, , which covers min/max clamping, provides the authoritative rules.
.container {
display: flex;
justify-content: space-between;
}
.card {
flex: 1 1 0%;
max-width: 320px;
min-width: 200px;
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
On a 1440 px viewport (assuming the container spans the full viewport width), three cards cap at 320 px each (960 px total), leaving 480 px of free space. space-between distributes 240 px gaps between adjacent cards. At narrower viewports where the cards haven’t yet reached 320 px, they continue to grow fluidly.
Fix 3: Cap the Container with max-width
Rather than constraining individual items, apply a max-width to the flex container itself. Items can still grow within the container, but the container stops expanding past a defined limit. Combined with margin: 0 auto, the layout centers on ultra-wide screens while preserving perceived spacing within the bounded area.
Fix 3 alone does not create gaps between flex items. It constrains the container width for visual comfort but does not resolve the free-space problem. If the design only needs items not to stretch absurdly wide, this suffices. If it needs visible gaps between items, combine Fix 3 with Fix 1, 2, or 4.
.container {
display: flex;
justify-content: space-between;
max-width: 1200px;
margin: 0 auto;
}
.card {
flex: 1 1 0%;
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
This approach does not restore free space within the flex container itself; items still fill the bounded 1200 px. space-between still distributes zero pixels between items. The container centers itself and keeps items at readable widths, which satisfies many designs. When actual gaps between items are required within the bounded container, pair this fix with Fix 1, Fix 2, or Fix 4.
Fix 4: Use gap Instead of (or Alongside) justify-content
The gap property on a flex container creates viewport-independent gutters that persist even when flex-grow absorbs free space. gap values reduce the space available to the flex algorithm: the container’s distributable space equals its total main size minus the combined gap widths, and flex-grow divides only that reduced remainder. The browser guarantees the gaps regardless of how items grow. If a 1200 px container has three items with flex-grow: 1 and gap: 2rem, the algorithm removes 4 rem (two gaps between three items) from the container’s available space, then distributes the remainder equally among the items. The items size proportionally to accommodate the gap.
.container {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
.card {
flex: 1 1 300px;
min-width: 250px;
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
The gap property is supported for flex containers in all current browsers (Chrome 84+, Firefox 63+, Safari 14.1+, Edge 84+), so no fallback is needed today. I measured this on a 1440 px viewport in Chromium: three cards with flex: 1 1 300px and gap: 2rem filled the row with exactly 32 px between them, while five cards wrapped onto a second row. One caveat: with flex-wrap: wrap, an item that lands alone on the last row still grows to the full width. If that matters, use the Grid version below, where tracks keep their size.
CSS Grid Alternative: Fixed Tracks with space-between
Why Grid Sidesteps the Problem
In CSS Grid, track sizes are defined on the container, not on children. Children occupy tracks but do not “grow” in the Flexbox sense. When tracks have fixed or max-capped widths, the total track width is less than the container width at wider viewports. That leftover space is genuine free space, and justify-content: space-between always has something to distribute. The flex-grow-consumes-free-space dynamic simply does not exist in Grid’s layout model.
How to Build It
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 320px));
justify-content: space-between;
gap: 1.5rem;
}
@media (max-width: 499px) {
.container {
justify-content: start;
}
}
.card {
box-sizing: border-box;
padding: 1.5rem;
background: #f4f4f4;
}
With minmax(min(250px, 100%), 320px), each track maxes out at 320 px and remains safe on viewports narrower than 250 px by falling back to 100% width. On a 1440 px container, four tracks (4 × 320 = 1280 px) plus three gaps (3 × 1.5 rem = 72 px, assuming a 16 px root font size; adjust if your project sets a different root font) total roughly 1352 px, leaving 88 px of free space (this value changes with root font size and actual container width) that space-between distributes. The layout adapts column count automatically via auto-fit while preserving visible spacing. Rows with fewer items than the maximum column count may spread items edge-to-edge because auto-fit collapses empty tracks. Use auto-fill or explicit item max-width constraints if consistent few-item behavior is required.
Annotated Before/After Comparison
The following side-by-side comparison captures the most common scenario and the simplest fix. This is the shareable reference for the core concept: flex-grow consumes free space, and removing it restores distributable space.
.container {
display: flex;
justify-content: space-between;
}
.card {
flex: 1 1 0%;
box-sizing: border-box;
padding: 1.5rem;
}
.container {
display: flex;
justify-content: space-between;
}
.card {
flex: 0 1 300px;
box-sizing: border-box;
padding: 1.5rem;
}
The only change is the flex shorthand value. Switching from 1 1 0% to 0 1 300px flips flex-grow from 1 to 0 and sets a concrete flex-basis. That single property change restores the entire space-between mechanism.
Quick-Reference Decision Tree
| Question | Answer | Action |
|---|---|---|
| Do items need to grow? | No | Fix 1: Set flex-grow: 0 (e.g., flex: 0 1 300px) |
| Do items need to grow? | Yes | Should items cap at a size? |
| Should items cap at a size? | Yes | Fix 2: Add max-width to items |
| Should items cap at a size? | No | Fix 4: Use gap for guaranteed gutters. (Fix 3 alone does not create gaps between items; combine Fix 3 with Fix 1, 2, or 4 if actual inter-item gaps are required.) |
| Open to using Grid? | Yes | Grid alternative: Fixed tracks with justify-content: space-between |
Why It All Comes Down to Free Space
The core insight behind every fix in this guide is a single spec rule: justify-content only acts on remaining free space, and a flex-grow factor greater than 0 can reduce that remaining space to zero. Once you understand that mechanism, the appropriate fix becomes a matter of deciding where to impose limits: on the items, on the container, or on the layout model itself.
Running the three-step diagnostic checklist (inspect free space, check flex-grow, verify container constraints) before reaching for workarounds saves time and prevents layering unnecessary overrides. For new layouts, combining gap with explicit item sizing through a defined flex-basis or max-width is the most resilient pattern for responsive design. It decouples gutter consistency from the growth algorithm and produces predictable spacing from narrow viewports through ultra-wide monitors.