How Does CSS Gap Work in Flexbox and Grid?

The CSS gap property defines the spacing, or gutters, between child elements in Flexbox, CSS Grid, and multi-column layouts without adding unwanted space to the outer edges. By establishing whitespace directly on the parent container, gap replaces complex margin hacks, simplifies responsive design, and creates clean, consistent spacing across both one-dimensional and two-dimensional layouts.

Understanding the Gap Property Syntax

The gap property is a shorthand that sets both row and column spacing simultaneously. It combines two individual sub-properties: row-gap and column-gap.

When declaring gap, you can specify one or two values:

.container {
  display: flex; /* or display: grid; */
  gap: 1.5rem; /* 1.5rem row and column spacing */
}

.custom-spaced-container {
  display: grid;
  row-gap: 2rem;
  column-gap: 1rem;
}

How Gap Operates in CSS Grid

In CSS Grid, gap defines the size of the grid tracks between designated rows and columns. It acts as an empty track divider:

  1. Fixed Gutters: Setting a gap size subtracts that total space from the grid container before calculating fractional units (fr).
  2. Perimeter Preservation: Gutter spaces exist strictly between grid cells. The container's outer edges touch the outer tracks unless explicit padding is applied.
  3. Empty Track Behavior: If grid items span multiple cells, the gap spacing is preserved under the spanned area automatically.
.grid-layout {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

In this layout, two 24px gutters are placed between the three columns, leaving the outer left and right boundaries flush with the grid container.

How Gap Operates in Flexbox

Flexbox uses gap to space adjacent flex items along both the main axis and the cross axis:

.flex-card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem; /* 1rem between wrapped lines, 1.5rem between items */
}

CSS Gap vs. Legacy Margin Techniques

Prior to widespread browser support for gap, developers relied on child margins and negative parent margins to simulate gutters:

/* Legacy Margin Technique */
.legacy-parent {
  margin: -10px;
}
.legacy-child {
  margin: 10px;
}

This approach created overflow issues, required extra wrapper elements, and demanded CSS pseudo-class resets like :last-child or :nth-child().

Using gap resolves these challenges: