CSS Gaps Module Level 1

Editor’s Draft,

More details about this document
This version:
https://drafts.csswg.org/css-gaps-1/
Latest published version:
https://www.w3.org/TR/css-gaps-1/
Previous Versions:
Feedback:
CSSWG Issues Repository
Editor:
Kevin Babbitt (Microsoft)
Suggest an Edit for this Spec:
GitHub Editor
Test Suite:
https://wpt.fyi/results/css/css-gaps/

Abstract

This module defines properties to specify spacing ("gaps") between items in container layouts. It also introduces properties for painting visible separators within those gaps.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-gaps” in the title, like this: “[css-gaps] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 18 August 2025 W3C Process Document.

1. Introduction

This section is not normative.

CSS Multicol 1 § 4 Column Gaps and Rules defined properties that allow authors to control the spacing between columns in a multicol container, and to paint visible separators such as lines in those spaces. We refer to these visible separators as gap decorations.

This specification expands upon the previously defined properties. It adds equivalent properties for the row direction, applies the full set of properties to other container types, and gives additional control over where and how gap decorations are painted.

1.1. Value Definitions

This specification follows the CSS property definition conventions from [CSS2] using the value definition syntax from [CSS-VALUES-3]. Value types not defined in this specification are defined in CSS Values & Units [CSS-VALUES-3]. Combination with other CSS modules may expand the definitions of these value types.

In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the CSS-wide keywords as their property value. For readability they have not been repeated explicitly.

2. Gaps Between Boxes

While margin and padding can be used to specify visual spacing around individual boxes, it’s sometimes more convenient to globally specify spacing between adjacent boxes within a given layout context, particularly when the spacing is different between sibling boxes as opposed to between the first/last box and the container’s edge.

The gap property, and its row-gap and column-gap sub-properties, provide this functionality for multi-column, flex, and grid layout.

A gap is either a column gap or row gap, whose definitions vary by type of container:

multi-column containers
A column gap is the gutter between adjacent column boxes, see [CSS-MULTICOL-1].

A row gap is the gutter between the rows of column boxes established by column-height, see [CSS-MULTICOL-2].

flex containers
When applied to the main axis (e.g. column gap in a row flex container), refers to the gutter between items (as if an additional fixed-size margin were inserted between adjacent flex items in a single line).

When applied to the cross axis (e.g. row gap in a row flex container), refers to the gutter between adjacent flex lines.

grid containers
Row gap and column gap, in the context of a grid container, refer to the gutters between grid rows and grid columns, respectively. See CSS Grid Layout 1 § 10.1 Gutters: the row-gap, column-gap, and gap properties for precise details.

Gutters effect a minimum spacing between items: additional spacing may be added by justify-content/align-content. Such additional space increases the size of the corresponding gaps.

In all cases, the gap disappears when it coincides with a fragmentation break. [CSS-BREAK-3]

Note: Table boxes do not use the gap properties to specify separation between their cells. Instead, they use the border-spacing property, which has slightly different functionality: it inherits, and it also specifies the additional spacing between the outermost cells and the border of the table (similar to space-evenly rather than space-between).

Column gaps in orange in a multicol container with a spanner element. Note that column gaps break when they encounter the spanner.
Gaps in a multicol container with `column-wrap: wrap`; column gaps in orange and row gaps in blue. Note that column gaps in multicol containers do not overlap row gaps, similar to flex.
Gaps in a grid container; column gaps in orange and row gaps in blue. Note the shaded areas where gaps overlap.
Gaps in a flex container; column gaps in orange and row gaps in blue. Note that, unlike in grid, gaps in flex do not overlap.

2.1. Row and Column Gutters: the row-gap and column-gap properties

Name: row-gap, column-gap
Value: normal | <length-percentage [0,∞]> | <line-width>
Initial: normal
Applies to: multi-column containers, flex containers, grid containers
Inherited: no
Percentages: see § 2.3 Percentages In gap Properties
Computed value: specified keyword, else a computed <length-percentage> value
Canonical order: per grammar
Animation type: by computed value type

These properties specify fixed-length gutters between items in the container, adding space between them—​in a manner similar to the space-between keyword of the content-distribution properties, but of a fixed size instead of as a fraction of remaining space. The column-gap property specifies spacing between “columns”, separating boxes in the container’s inline axis similar to inline-axis margin; while row-gap indicates spacing between “rows”, separating boxes in the container’s block axis.

Values have the following meanings:

<length-percentage [0,∞]>
<line-width>

Specifies a row gap or column gap as defined by the layout modes to which it applies.

Negative values are invalid. For percentages, see § 2.3 Percentages In gap Properties.

normal

The value normal represents a used value of 1em on multi-column containers, and a used value of 0px in all other contexts.

2.2. Gap Shorthand: the gap property

Name: gap
Value: <'row-gap'> <'column-gap'>?
Initial: see individual properties
Applies to: multi-column containers, flex containers, grid containers
Inherited: no
Percentages: refer to corresponding dimension of the content area
Computed value: see individual properties
Canonical order: per grammar
Animation type: by computed value type

This property is a shorthand that sets row-gap and column-gap in one declaration. If <'column-gap'> is omitted, it’s set to the same value as <'row-gap'>.

A diagram showing how margins and padding add to the visible gutter size

Note: The gap property is only one component of the visible “gutter” or “alley” created between boxes. Margins, padding, or the use of distributed alignment may increase the visible separation between boxes beyond what is specified in gap.

2.3. Percentages In gap Properties

In general, gaps introduced by the gap properties are intended to act like an empty item/track/etc with the gap’s size; in other words, an author should be able to reproduce the effects of gap by just inserting additional empty items/tracks/etc into the container.

gap always resolves percentages against the corresponding size of the content box of the element. When this size is definite, the behavior is well-defined and consistent across layout modes. But since different layout modes treat cyclic percentage sizes for items/tracks/etc differently, gap does as well:

In Grid Layout

As in the min size properties and margins/paddings [CSS-SIZING-3], cyclic percentage sizes resolve against zero for determining intrinsic size contributions, but resolve against the box’s content box when laying out the box’s contents.

In Flex Layout

Cyclic percentage sizes resolve against zero in all cases.

2.4. Legacy Gap Properties: the grid-row-gap, grid-column-gap, and grid-gap properties

The Grid Layout module was originally written with its own set of gutter properties, before all such properties were unified into the existing row-gap/column-gap naming. For compatibility with legacy content, these grid-prefixed names must be supported as follows:

3. Gap decorations

Gaps may contain a gap decoration, which is a visible separator (such as a line) painted between adjacent boxes.

Gap decorations do not take up space. That is, the presence or width of a gap decoration will not alter the placement of anything else. If a gap decoration is wider than its gap, any adjacent boxes will overlap the decoration, and in some cases the decoration may extend outside the box of the container.

Gap decorations are painted just above the border of the container. For scrollable containers, note that while the border and background of the container aren’t scrolled, the decorations need to scroll along with items in the container.

Gap decorations follow the definitions of "column" and "row" laid out by the container to which the properties are applied. They depend on the container type taking writing mode into account when determining the meanings of these terms. For examples, see: CSS Multicol 2 § 3 The multi-column model, CSS Flexbox 1 § 5.1 Flex Flow Direction: the flex-direction property, and CSS Grid Layout 1 § 3 Grid Layout Concepts and Terminology.

Properties in this specification whose names begin with "column" apply to column gaps, and properties in this specification whose names begin with "row" apply to row gaps.

3.1. Geometry

Gap decorations are painted within a gap as one or more gap decoration segments.

3.1.1. Segment endpoints

A segment endpoint is a point on a gap’s centerline where a gap decoration segment may start or end. There are two endpoint types:

To create segment endpoints for a gap G:
  1. Bounds of a Gap:

    Create endpoints at G’s two bounds:

    When a gap runs to the content boundary, these endpoints coincide with the corresponding content edge.

  2. Within a Gap:

    A gap junction is a region of G where one or more gaps abut or overlap G. Two segment endpoints are created for each gap junction:

    This ordering (end segment endpoint, start segment endpoint) reflects that the gap junction corresponds to the end of one track/item/column and the beginning of another.

The following examples illustrate the locations of segment endpoints, with a purple + for start segment endpoints and a green + for end segment endpoints in each case. Gap junctions are shown with a dashed box.
.grid-with-spans {
  display: grid;
  grid-template: repeat(4, 100px) / repeat(4, 100px);
  gap: 20px;
  background: rgb(255 255 128);
}
.grid > * {
  border: 1px dashed black;
}
Locations of segment endpoints and gap junctions in a grid with spanning items. Segment endpoints are created at the bounds of each gap (which coincide with the edges of the container), and within each gap in an end-start manner where the row and column gaps overlap.
.flex {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  width: 500px;
  background: rgb(255 255 128);
}
.flex > * {
  border: 1px dashed black;
}
Locations of segment endpoints and gap junctions in a flex container. Column gaps create endpoints at their bounds; some bounds coincide with the container edges (like the start of the gaps between #1 and #2, and #2 and #3 which coincide with the top edge of the container, and the end of the gap between #7 and #8 which coincides with the bottom edge of the container). Row gaps (between flex lines) create endpoints at their bounds, which coincide with the left and right edges of the container. Where column gaps abut row gaps, two endpoints are created in an end-start manner.
.multi-column {
  column-count: 3;
  column-width: 100px;
  column-height: 50px;
  column-wrap: wrap;
  gap: 20px;
  background: rgb(255 255 128);
}

.multi-column > * {
  height: 100px;
  border: 1px dashed black;
}	
Locations of segment endpoints and gap junctions in a multi-column container. Column gaps (between column boxes) create endpoints at their bounds; some bounds coincide with the container edges (like the starts of the first 2 column gaps which coincide with the top edge, and the ends of the last 2 column gaps which coincide with the bottom edge). The row gap (between rows of column boxes) creates endpoints at its bounds, which coincide with the left and right edges of the container. Where column gaps abut the row gap, two endpoints are created in an end-start manner.

3.1.2. Gap decoration segments

Definitions

A gap decoration segment is formed by pairing a start segment endpoint with an end segment endpoint. Each gap forms a collection of gap decoration segments.

In this section, we represent a gap decoration segment s as s = [s.start, s.end], where s.start is the start segment endpoint of the segment, and s.end is the end segment endpoint of the segment.

Let UNION(s1, s2) be equal to [s1.start, s2.end].

A gap decoration segment is flanked by spanning items if, for every gap junction between its endpoints, there exist items on opposing sides of the gap that span across all perpendicular gaps contributing to that junction.

In the context of a given gap, a pair of segment endpoints a and b is considered discontiguous if a line segment from a to b, with the same width as the gap, intersects a child item in the container.

Algorithms
To determine gap decoration segments for a given gap G:
  1. Let S be an empty list.
  2. Let endpoints be the result of creating segment endpoints for G, ordered by their position along G’s centerline from start to end.

    Note: This list is guaranteed to contain an even number of elements that strictly alternate between start segment endpoint and end segment endpoint, beginning with a start segment endpoint.

  3. If endpoints is empty, return S.
  4. Let break be the used value of either column-rule-break or row-rule-break, whichever applies to the gap.
  5. If break is none:
    1. Let first be the first item in endpoints.
    2. Let last be the last item in endpoints.
    3. Create a gap decoration segment segment = [first, last].
    4. Apply offsets to segment, then append it to S.
    5. Return S.
  6. Empty Check: If endpoints is empty, return S.
  7. Create a gap decoration segment s from the first two items in endpoints. Remove them both from the list.
  8. If s’s endpoints are discontiguous, go back to Empty Check.
  9. While endpoints is not empty:
    1. Create a gap decoration segment next from the first two items in endpoints, leaving them both in the list.
    2. Let candidate be UNION(s, next).
    3. If candidate’s endpoints are discontiguous, exit this loop.
    4. If break is intersection and candidate is not flanked by spanning items, exit this loop.
    5. Remove the first two items from endpoints.
    6. Set s to UNION(s, next).
  10. Apply offsets to s, then append it to S.
  11. Go back to Empty Check.
To apply offsets to a segment s = [start, end]:
  1. Offset start by the used value of the applicable rule-inset property.
  2. Offset end by the used value of the applicable rule-inset property.
  3. Update s with the adjusted [start, end].
Illustration of gap decoration segments (blue and red rectangles) in a grid container. The segments are drawn between pairs of segment endpoints, with start segment endpoints marked with purple crosses and end segment endpoints marked with green crosses.
Illustration of gap decoration segments (blue and red rectangles) in a flex container. The segments are drawn between pairs of segment endpoints, with start segment endpoints marked with purple crosses and end segment endpoints marked with green crosses.
Illustration of gap decoration segments (blue and red rectangles) in a multicol container (with column-wrap: wrap). The segments are drawn between pairs of segment endpoints, with start segment endpoints marked with purple crosses and end segment endpoints marked with green crosses.
Illustration of gap decoration segments (blue and red rectangles) in a flex container. The segments are drawn between pairs of segment endpoints, with start segment endpoints marked with purple crosses and end segment endpoints marked with green crosses.
Illustration of gap decoration segments (blue and red rectangles) in a flex container. The segments are drawn between pairs of segment endpoints, with start segment endpoints marked with purple crosses and end segment endpoints marked with green crosses.
Tests

3.2. Break behaviors at intersections: The column-rule-break, row-rule-break, and rule-break properties

Name: column-rule-break, row-rule-break
Value: none | normal | intersection
Initial: normal
Applies to: grid containers, flex containers, multicol containers, and grid lanes containers
Inherited: no
Percentages: n/a
Computed value: as specified
Canonical order: per grammar
Animation type: discrete

These properties set the behavior for breaking decorations within a given gap into segments at visible "T" or "cross" intersections formed by items in the container. Precise details for how to apply these values are given in the steps to determine gap decoration segments.

none
Gap decorations do not start or end at visible "T" or "cross" intersections. Instead, a single continuous decoration is painted from one end of the gap to the other.
normal
Behavior depends on the type of container.
Grid containers
Gap decorations start and end at visible "T" intersections but continue through visible "cross" intersections.
Flex containers
Behaves the same as none.
Multicol containers
On column-rule-break, behaves the same as intersection. On row-rule-break, behaves the same as none.
intersection
Gap decorations start and end at visible "T" and "cross" intersections.
Tests
Name: rule-break
Value: <'column-rule-break'>
Initial: see individual properties
Applies to: Same as column-rule-break and row-rule-break
Inherited: see individual properties
Percentages: see individual properties
Computed value: see individual properties
Animation type: see individual properties
Canonical order: per grammar

This shorthand property sets column-rule-break and row-rule-break to the same value.

Tests

The following examples illustrate various settings for the *-rule-break properties.

.break-normal-grid {
  display: grid;
  grid-template: repeat(4, 100px) / repeat(4, 100px);
  gap: 20px;
  row-rule: 6px solid red;
  column-rule: 6px solid blue;
  rule-break: normal;
}
Default break behavior for gap decorations in a grid. Each decoration stops when it encounters an item spanning across the gap.
.break-none-grid {
  display: grid;
  grid-template: repeat(4, 100px) / repeat(4, 100px);
  gap: 20px;
  row-rule: 6px solid red;
  column-rule: 6px solid blue;
  rule-break: none;
}
Grid gap decorations with no breaks. Note that the gap decorations extend "behind" items placed in the grid.
.break-intersection-grid {
  display: grid;
  grid-template: repeat(4, 100px) / repeat(4, 100px);
  gap: 20px;
  row-rule: 6px solid red;
  column-rule: 6px solid blue;
  rule-break: intersection;
}
Grid gap decorations contained within each gap decoration segment that is not flanked by spanning items on opposing sides.
.break-normal-multicol {
  column-width: 150px;
  column-height: 300px;
  gap: 1em;
  row-rule: 4px solid red;
  column-rule: 4px solid blue;
  rule-break: normal;
}
Multicol gap decorations with rule-break set to normal. Note that in the column direction it behaves as if rule-break were set to intersection, while in the row direction it behaves as if rule-break were set to none.
.break-intersection-multicol {
  column-width: 150px;
  column-height: 300px;
  gap: 1em;
  row-rule: 4px solid red;
  column-rule: 4px solid blue;
  rule-break: intersection;
}
Multicol gap decorations with rule-break set to intersection.
.break-normal-flex {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  row-rule: 6px solid red;
  column-rule: 6px solid blue;
  rule-break: normal;
}
Default break behavior for gap decorations in a flex container.
Note that each flex line has its own distinct gaps between items. This has two implications:
  1. Gap decorations in adjacent flex lines are separate from each other even if the gaps happen to line up.
  2. none would have the same visual effect as normal.
.break-intersection-flex {
  display: flex;
  flex-wrap: wrap;
  width: 500px;
  gap: 20px;
  row-rule: 6px solid red;
  column-rule: 6px solid blue;
  rule-break: intersection;
}
Flexbox gap decorations contained within each gap decoration segment.

3.3. Adjusting gap decoration endpoints: The rule-inset properties

Name: column-rule-inset-cap-start, column-rule-inset-cap-end, column-rule-inset-junction-start, column-rule-inset-junction-end, row-rule-inset-cap-start, row-rule-inset-cap-end, row-rule-inset-junction-start, row-rule-inset-junction-end
Value: <inset-value>
Initial: 0
Applies to: grid containers, flex containers, multicol containers, and grid lanes containers
Inherited: no
Percentages: refer to the crossing gap width
Computed value: as specified
Canonical order: per grammar
Animation type: by computed value type
<inset-value> = <length-percentage> | overlap-join

These properties can be used to offset the start and end points of gap decorations relative to the segment endpoints which would normally determine where decorations start and end.

A junction segment endpoint is a segment endpoint at a gap junction where one or more other gap decoration segments are also present.

A cap segment endpoint is any segment endpoint that is not a junction segment endpoint. This includes endpoints at the container’s content edges, as well as endpoints at a gap junction where no other gap decoration segment is present.

.simple-grid {
  rule-break: intersection;
  rule-visibility-items: between;
}
In a fully populated grid, every interior gap junction produces junction segment endpoints (marked J), while the container’s content edges produce cap segment endpoints (marked C).
.simple-grid-with-empty-cells {
  rule-break: intersection;
  rule-visibility-items: between;
}
When a gap decoration segment terminates at an interior gap junction where no other gap decoration segment is present, its endpoint is a cap segment endpoint.
.donut-grid-layout {
  rule-break: intersection;
  rule-visibility-items: between;
}
In a "donut" grid layout, where items surround an empty space in the middle of the container, endpoints bordering the empty interior region are cap segment endpoints.

Percentages are resolved against the crossing gap width, defined as follows:

Segment endpoints at a gap junction
The crossing gap width is the size of the gap junction in the same dimension as the gap in which the segment endpoint lies (the row dimension for row gaps and the column dimension for column gaps).