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).
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'>.
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:
-
grid-row-gap as a legacy name alias of the row-gap property
-
grid-column-gap as a legacy name alias of the column-gap property
-
grid-gap as a legacy name alias of the gap property
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:
- start segment endpoint: Point closest to the start side of the gap.
- end segment endpoint: Point closest to the end side of the gap.
-
Bounds of a Gap:
Create endpoints at G’s two bounds:
- At the centerpoint of G’s start edge, create a start segment endpoint.
- At the centerpoint of G’s end edge, create an end segment endpoint.
When a gap runs to the content boundary, these endpoints coincide with the corresponding content edge.
-
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:
- Entering a gap junction: At the point where a cross gap appears on at least one side of G, create an end segment endpoint.
- Exiting a gap junction: At the point where no cross gap exists on either side of G, create a start segment endpoint.
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.
.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;
}
.flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
width: 500px;
background: rgb(255 255 128);
}
.flex > * {
border: 1px dashed black;
}
.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;
}
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
- Let S be an empty list.
-
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.
- If endpoints is empty, return S.
- Let break be the used value of either column-rule-break or row-rule-break, whichever applies to the gap.
-
If break is none:
- Let first be the first item in endpoints.
- Let last be the last item in endpoints.
- Create a gap decoration segment segment = [first, last].
- Apply offsets to segment, then append it to S.
- Return S.
- Empty Check: If endpoints is empty, return S.
- Create a gap decoration segment s from the first two items in endpoints. Remove them both from the list.
- If s’s endpoints are discontiguous, go back to Empty Check.
-
While endpoints is not empty:
- Create a gap decoration segment next from the first two items in endpoints, leaving them both in the list.
- Let candidate be UNION(s, next).
- If candidate’s endpoints are discontiguous, exit this loop.
- If break is intersection and candidate is not flanked by spanning items, exit this loop.
- Remove the first two items from endpoints.
- Set s to UNION(s, next).
- Apply offsets to s, then append it to S.
- Go back to Empty Check.
- Offset start by the used value of the applicable rule-inset property.
- Offset end by the used value of the applicable rule-inset property.
- Update s with the adjusted [start, end].
Tests
- flex-gap-decorations-001.html (live test) (source)
- flex-gap-decorations-006.html (live test) (source)
- flex-gap-decorations-007.html (live test) (source)
- flex-gap-decorations-008.html (live test) (source)
- flex-gap-decorations-015.html (live test) (source)
- flex-gap-decorations-016.html (live test) (source)
- flex-gap-decorations-020.html (live test) (source)
- flex-gap-decorations-021.html (live test) (source)
- flex-gap-decorations-022.html (live test) (source)
- flex-gap-decorations-023.html (live test) (source)
- flex-gap-decorations-024.html (live test) (source)
- flex-gap-decorations-025.html (live test) (source)
- flex-gap-decorations-026-crash.html (live test) (source)
- flex-gap-decorations-027.html (live test) (source)
- flex-gap-decorations-032.html (live test) (source)
- flex-gap-decorations-033.html (live test) (source)
- flex-gap-decorations-039.html (live test) (source)
- flex-gap-decorations-040.html (live test) (source)
- flex-gap-decorations-041.html (live test) (source)
- flex-gap-decorations-042.html (live test) (source)
- flex-gap-decorations-043.html (live test) (source)
- flex-gap-decorations-044.html (live test) (source)
- flex-gap-decorations-045.html (live test) (source)
- flex-gap-decorations-046.html (live test) (source)
- flex-gap-decorations-047.html (live test) (source)
- flex-gap-decorations-048.html (live test) (source)
- flex-gap-decorations-049.html (live test) (source)
- flex-gap-decorations-056.html (live test) (source)
- flex-gap-decorations-057.html (live test) (source)
- flex-gap-decorations-058.html (live test) (source)
- flex-gap-decorations-059.html (live test) (source)
- flex-gap-decorations-060.html (live test) (source)
- flex-gap-decorations-061.html (live test) (source)
- flex-gap-decorations-repaint-on-child-resize.html (live test) (source)
- flex-gap-decorations-repaint-on-container-shift.html (live test) (source)
- flex-gap-decorations-writing-mode.html (live test) (source)
- grid-gap-decorations-001.html (live test) (source)
- grid-gap-decorations-029.html (live test) (source)
- grid-gap-decorations-030.html (live test) (source)
- grid-gap-decorations-031.html (live test) (source)
- grid-gap-decorations-032.html (live test) (source)
- grid-gap-decorations-033.html (live test) (source)
- grid-gap-decorations-034.html (live test) (source)
- grid-gap-decorations-035.html (live test) (source)
- grid-gap-decorations-036.html (live test) (source)
- grid-gap-decorations-037.html (live test) (source)
- grid-gap-decorations-041-crash.html (live test) (source)
- grid-gap-decorations-042.html (live test) (source)
- grid-gap-decorations-043-crash.html (live test) (source)
- grid-gap-decorations-044-crash.html (live test) (source)
- grid-gap-decorations-045.html (live test) (source)
- grid-gap-decorations-046.html (live test) (source)
- grid-gap-decorations-047.html (live test) (source)
- grid-gap-decorations-066.html (live test) (source)
- grid-gap-decorations-repaint-on-child-resize.html (live test) (source)
- grid-gap-decorations-repaint-on-item-position-change.html (live test) (source)
- grid-gap-decorations-repaint-on-item-span-change.html (live test) (source)
- grid-gap-decorations-writing-mode.html (live test) (source)
- subgrid-gap-decorations-001.html (live test) (source)
- subgrid-gap-decorations-002.html (live test) (source)
- subgrid-gap-decorations-003.html (live test) (source)
- subgrid-gap-decorations-009.html (live test) (source)
- subgrid-gap-decorations-010.html (live test) (source)
- subgrid-gap-decorations-011.html (live test) (source)
- subgrid-gap-decorations-012.html (live test) (source)
- subgrid-gap-decorations-013.html (live test) (source)
- subgrid-gap-decorations-014.html (live test) (source)
- subgrid-gap-decorations-015.html (live test) (source)
- subgrid-gap-decorations-016.html (live test) (source)
- subgrid-gap-decorations-018.html (live test) (source)
- multicol-gap-decorations-001.html (live test) (source)
- multicol-gap-decorations-002.html (live test) (source)
- multicol-gap-decorations-003.html (live test) (source)
- multicol-gap-decorations-005.html (live test) (source)
- multicol-gap-decorations-006.html (live test) (source)
- multicol-gap-decorations-007.html (live test) (source)
- multicol-gap-decorations-013.html (live test) (source)
- multicol-gap-decorations-015.html (live test) (source)
- multicol-gap-decorations-016.html (live test) (source)
- multicol-gap-decorations-018.html (live test) (source)
- multicol-gap-decorations-024.html (live test) (source)
- multicol-gap-decorations-040.html (live test) (source)
- multicol-gap-decorations-repaint-on-content-resize.html (live test) (source)
- multicol-gap-decorations-writing-mode.html (live test) (source)
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
- flex-gap-decorations-009.html (live test) (source)
- flex-gap-decorations-010.html (live test) (source)
- flex-gap-decorations-028.html (live test) (source)
- flex-gap-decorations-031.html (live test) (source)
- flex-gap-decorations-034.html (live test) (source)
- flex-gap-decorations-035.html (live test) (source)
- flex-gap-decorations-036.html (live test) (source)
- flex-gap-decorations-037.html (live test) (source)
- flex-gap-decorations-050.html (live test) (source)
- flex-gap-decorations-051.html (live test) (source)
- flex-gap-decorations-052.html (live test) (source)
- grid-gap-decorations-006.html (live test) (source)
- grid-gap-decorations-007.html (live test) (source)
- grid-gap-decorations-008.html (live test) (source)
- grid-gap-decorations-009.html (live test) (source)
- grid-gap-decorations-040.html (live test) (source)
- subgrid-gap-decorations-004.html (live test) (source)
- subgrid-gap-decorations-005.html (live test) (source)
- subgrid-gap-decorations-006.html (live test) (source)
- multicol-gap-decorations-014.html (live test) (source)
- multicol-gap-decorations-020.html (live test) (source)
- multicol-gap-decorations-025.html (live test) (source)
- multicol-gap-decorations-026.html (live test) (source)
- multicol-gap-decorations-034.html (live test) (source)
| 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;
}
.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;
}
.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;
}
.break-normal-multicol {
column-width: 150px;
column-height: 300px;
gap: 1em;
row-rule: 4px solid red;
column-rule: 4px solid blue;
rule-break: normal;
}
.break-intersection-multicol {
column-width: 150px;
column-height: 300px;
gap: 1em;
row-rule: 4px solid red;
column-rule: 4px solid blue;
rule-break: intersection;
}
.break-normal-flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
row-rule: 6px solid red;
column-rule: 6px solid blue;
rule-break: normal;
}
- Gap decorations in adjacent flex lines are separate from each other even if the gaps happen to line up.
- 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;
}
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;
}
.simple-grid-with-empty-cells {
rule-break: intersection;
rule-visibility-items: between;
}
.donut-grid-layout {
rule-break: intersection;
rule-visibility-items: between;
}
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).