Why Does CSS Grid-Gap Cause an Overflow?
Understanding why grid-gap causes overflow with percentage-based columns and how to fix it using fr units, minmax(), and calc()
Introduction
A common CSS Grid pitfall: you define percentage-based columns that add up to 100%, add a grid-gap, and suddenly your layout overflows. This guide explains why this happens and provides three reliable solutions.
The Problem
You have a 3-column grid container:
.body {
display: grid;
grid-template-columns: 25% 50% 25%;
grid-gap: 10px;
}
The total width of those columns is 100%. But when you add gutters between the columns (and rows), the math breaks:
25% + 50% + 25% + 10px + 10px = 100% + 20px > 100%
This results in an overflow condition.
Important note: grid-gap properties apply only between grid items — never between items and the container. That's why we calculate two grid gaps (between three columns), not four.
Solution 1: Use fr Units (Recommended)
fr units apply only to free space — they're calculated after any grid-gap lengths are applied. This makes them the cleanest solution:
.body {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
gap: 10px; /* Modern shorthand for grid-gap */
}
How fr Units Work
/* Equal columns */
grid-template-columns: 1fr 1fr 1fr;
/* Proportional columns */
grid-template-columns: 2fr 1fr 1fr; /* First column twice as wide */
/* Mixed with fixed values */
grid-template-columns: 200px 1fr 1fr; /* Fixed sidebar, flexible content */
Benefits of fr units:
- ✅ Automatically account for gaps
- ✅ Responsive by nature
- ✅ Clean, readable syntax
- ✅ No overflow issues
Solution 2: Use minmax() Function
The minmax() function allows columns to shrink to fit the parent container, preventing overflow:
.body {
display: grid;
grid-template-columns: minmax(auto, 25%) minmax(auto, 50%) minmax(auto, 25%);
gap: 10px;
}
How minmax() Works
/* Syntax: minmax(minimum, maximum) */
/* Column can shrink to 0 but won't exceed 25% */
minmax(0, 25%)
/* Column won't shrink below 200px, won't exceed 1fr */
minmax(200px, 1fr)
/* Auto minimum - content determines minimum size */
minmax(auto, 50%)
Benefits of minmax():
- ✅ Keeps percentage-based sizing
- ✅ Prevents overflow by allowing shrinkage
- ✅ Works with any unit type
- ✅ Great for responsive breakpoints
Solution 3: Use calc() for Fixed Columns
If you have a fixed number of equal-width columns, use calc() to subtract the gap space:
.grid {
display: grid;
grid-template-columns: repeat(4, calc(25% - 0.75em));
gap: 1em;
}
The Math Behind calc()
For 4 columns with 1em gap:
- Total gap space:
3 × 1em = 3em(gaps between 4 columns) - Space per column:
3em ÷ 4 = 0.75em - Each column:
25% - 0.75em
/* 2 columns */
grid-template-columns: repeat(2, calc(50% - 0.5em));
gap: 1em;
/* Total gap: 1em, per column: 0.5em */
/* 3 columns */
grid-template-columns: repeat(3, calc(33.333% - 0.667em));
gap: 1em;
/* Total gap: 2em, per column: 0.667em */
/* 5 columns */
grid-template-columns: repeat(5, calc(20% - 0.8em));
gap: 1em;
/* Total gap: 4em, per column: 0.8em */
Benefits of calc():
- ✅ Exact control over column widths
- ✅ Works when you need specific percentages
- ✅ Predictable across all viewports
Comparing the Solutions
| Solution | Best For | Example |
|---|---|---|
fr units | Flexible, proportional layouts | 1fr 2fr 1fr |
minmax() | Percentage-based with flexibility | minmax(auto, 25%) |
calc() | Fixed, exact column widths | calc(25% - 0.75em) |
Modern CSS: The gap Property
The gap property is the modern shorthand that works for both Grid and Flexbox:
/* Old syntax (still works) */
grid-gap: 10px;
grid-column-gap: 10px;
grid-row-gap: 10px;
/* Modern syntax (preferred) */
gap: 10px; /* Both row and column */
gap: 10px 20px; /* Row gap 10px, column gap 20px */
row-gap: 10px;
column-gap: 20px;
Real-World Example
/* ❌ Problematic - overflows */
.page-layout {
display: grid;
grid-template-columns: 20% 60% 20%;
gap: 20px;
}
/* ✅ Solution 1: fr units */
.page-layout {
display: grid;
grid-template-columns: 1fr 3fr 1fr;
gap: 20px;
}
/* ✅ Solution 2: minmax() */
.page-layout {
display: grid;
grid-template-columns: minmax(auto, 20%) minmax(auto, 60%) minmax(auto, 20%);
gap: 20px;
}
/* ✅ Solution 3: calc() */
.page-layout {
display: grid;
grid-template-columns: repeat(3, calc(33.333% - 13.333px));
gap: 20px;
}
Common Pitfalls
1. Mixing Percentage and Fixed Gaps
/* ❌ Will overflow */
grid-template-columns: 50% 50%;
gap: 20px;
/* ✅ Use fr instead */
grid-template-columns: 1fr 1fr;
gap: 20px;
2. Forgetting Gap Count
/* 4 columns have 3 gaps, not 4 */
/* ❌ Wrong: 4 gaps */
grid-template-columns: repeat(4, calc(25% - 1em));
gap: 1em;
/* ✅ Correct: 3 gaps → 3em ÷ 4 = 0.75em */
grid-template-columns: repeat(4, calc(25% - 0.75em));
gap: 1em;
3. Using gap with auto Columns
/* ❌ auto columns don't work well with calc() */
grid-template-columns: auto auto auto;
gap: 20px;
/* ✅ Use fr for flexible columns */
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
Conclusion
CSS Grid gaps causing overflow is a common issue with a simple explanation: percentage columns don't account for gap space. The three solutions are:
frunits — The modern, flexible approach (recommended for most cases)minmax()— When you need percentage-based sizing with flexibilitycalc()— When you need exact, predictable column widths
Choose the solution that best fits your layout needs, and remember: fr units are almost always the right answer for proportional layouts.
#css #grid #layout #responsive-design #web-development #frontend