Asher Cohen
Back to posts

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

SolutionBest ForExample
fr unitsFlexible, proportional layouts1fr 2fr 1fr
minmax()Percentage-based with flexibilityminmax(auto, 25%)
calc()Fixed, exact column widthscalc(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:

  1. fr units — The modern, flexible approach (recommended for most cases)
  2. minmax() — When you need percentage-based sizing with flexibility
  3. calc() — 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