1. Introduction
This section is not normative.
CSS Multicol 1 § 4 Column Gaps and Rules allows for rules to be drawn between columns in a multicol container. This specification expands upon the column-rule-width, column-rule-style, and column-rule-color properties, adding equivalents in the row direction, expanding their application to other container layouts, and giving advanced 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
Various layouts in CSS such as multicol containers, flex containers, grid containers, and grid lanes containers position child boxes adjacent to each other with gaps, also known as gutters, between them.
For the purposes of this specification, gap, column gap, and row gap are defined as follows depending on the type of container:
- multi-column containers
-
In the column direction, gap (column gap) refers to the gutter between adjacent column boxes within each multicol line,
see [CSS-MULTICOL-1].
In the row direction, gap (row gap) refers to the gutter between the rows of column boxes established by column-height,
see [CSS-MULTICOL-2].
Note: It is important to note that column gaps in Multicol containers break when encountering a spanner element or a row gap.
- flex containers
-
In the main axis
(e.g. column-gap in a row flex container),
gap (column gap) refers to the gutter between items within a single flex line.
In the cross axis (e.g. row-gap in a row flex container), gap (row gap) refers to the gutter between adjacent flex lines.
- grid containers
- row gaps and column gaps 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.
3. Gap decorations
Gaps may contain a gap decoration, which is a visible separator (such as a line) painted between adjacent boxes.
.grid-with-spans {
display: grid;
grid-template: repeat(4, 100px) / repeat(4, 100px);
gap: 20px;
row-rule: 6px solid red;
column-rule: 6px solid blue;
}
.flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
width: 500px;
row-rule: 6px solid red;
column-rule: 6px solid blue;
}
3.1. Layout and painting
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 are painted within a gap as one or more gap decoration segments.
3.1.1. Segment Endpoints
A gap 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 at which a segment begins.
- end segment endpoint: Point at which a segment ends.
Segment endpoints are created at the following locations:
-
Bounds of a Gap:
For each gap, endpoints are created at its two bounds:
- At the start of the gap, a start segment endpoint is created.
- At the end of the gap, an end segment endpoint is created.
When a gap runs to the content boundary, these endpoints coincide with the corresponding content edge.
-
Within a Gap:
When a cross/perpendicular gap touches a given gap (either overlapping it, or abutting it without overlapping), two endpoints are created which align with the boundaries of the cross/perpendicular gap:
- The earlier boundary creates an end segment endpoint.
- The later boundary creates a start segment endpoint.
This ordering (end segment endpoint, start segment endpoint) reflects that the junction corresponds to the end of one track/item/column-box and the beginning of the next.
.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;
}
NB: Should I mention different layout types and their gap behaviors here? Or is it implied? From preceeding sections. Feel Like I should for emphasis.
Tests
CSS Box Alignment 3 § 8.1 Row and Column Gutters: the row-gap and column-gap properties specifies that gaps disappear where they coincide with a fragmentation break. Because there is no gap in such locations, no gap decoration is drawn in them either.
Tests
- flex-gap-decorations-fragmentation-001.html (live test) (source)
- flex-gap-decorations-fragmentation-002.html (live test) (source)
- flex-gap-decorations-fragmentation-003.html (live test) (source)
- flex-gap-decorations-fragmentation-004.html (live test) (source)
- flex-gap-decorations-fragmentation-005.html (live test) (source)
- flex-gap-decorations-fragmentation-006.html (live test) (source)
- flex-gap-decorations-fragmentation-007.html (live test) (source)
- flex-gap-decorations-fragmentation-008.html (live test) (source)
- flex-gap-decorations-fragmentation-009.html (live test) (source)
- flex-gap-decorations-fragmentation-010.html (live test) (source)
- flex-gap-decorations-fragmentation-011.html (live test) (source)
- flex-gap-decorations-fragmentation-012.html (live test) (source)
- flex-gap-decorations-fragmentation-013.html (live test) (source)
- flex-gap-decorations-fragmentation-014.html (live test) (source)
- grid-gap-decorations-fragmentation-001.html (live test) (source)
- grid-gap-decorations-fragmentation-002.html (live test) (source)
- grid-gap-decorations-fragmentation-003.html (live test) (source)
- grid-gap-decorations-fragmentation-004.html (live test) (source)
- grid-gap-decorations-fragmentation-005.html (live test) (source)
- grid-gap-decorations-fragmentation-006.html (live test) (source)
- grid-gap-decorations-fragmentation-007.html (live test) (source)
- grid-gap-decorations-fragmentation-008.html (live test) (source)
- grid-gap-decorations-fragmentation-009.html (live test) (source)
- grid-gap-decorations-fragmentation-010.html (live test) (source)
- grid-gap-decorations-fragmentation-011.html (live test) (source)
- grid-gap-decorations-fragmentation-012.html (live test) (source)
- grid-gap-decorations-fragmentation-013.html (live test) (source)
- grid-gap-decorations-fragmentation-014.html (live test) (source)
- grid-gap-decorations-fragmentation-015.html (live test) (source)
- grid-gap-decorations-fragmentation-016.html (live test) (source)
- grid-gap-decorations-fragmentation-017.html (live test) (source)
- grid-gap-decorations-fragmentation-018-crash.html (live test) (source)
- grid-gap-decorations-fragmentation-019-crash.html (live test) (source)
- grid-gap-decorations-fragmentation-020.html (live test) (source)
- grid-gap-decorations-fragmentation-021.html (live test) (source)
- grid-gap-decorations-fragmentation-022.html (live test) (source)
- grid-gap-decorations-fragmentation-023.html (live test) (source)
- grid-gap-decorations-fragmentation-024.html (live test) (source)
- grid-gap-decorations-fragmentation-025.html (live test) (source)
- grid-gap-decorations-fragmentation-026.html (live test) (source)
- grid-gap-decorations-fragmentation-027.html (live test) (source)
- subgrid-gap-decorations-fragmentation-001.html (live test) (source)
- subgrid-gap-decorations-fragmentation-002.html (live test) (source)
- subgrid-gap-decorations-fragmentation-003.html (live test) (source)
- subgrid-gap-decorations-fragmentation-004.html (live test) (source)
- subgrid-gap-decorations-fragmentation-005.html (live test) (source)
- subgrid-gap-decorations-fragmentation-006.html (live test) (source)
- subgrid-gap-decorations-fragmentation-007.html (live test) (source)
- subgrid-gap-decorations-fragmentation-008.html (live test) (source)
- subgrid-gap-decorations-fragmentation-009.html (live test) (source)
- subgrid-gap-decorations-fragmentation-010.html (live test) (source)
- subgrid-gap-decorations-fragmentation-011.html (live test) (source)
- subgrid-gap-decorations-fragmentation-012.html (live test) (source)
- subgrid-gap-decorations-fragmentation-013.html (live test) (source)
- subgrid-gap-decorations-fragmentation-014.html (live test) (source)
- subgrid-gap-decorations-fragmentation-015.html (live test) (source)
- subgrid-gap-decorations-fragmentation-016.html (live test) (source)
- subgrid-gap-decorations-fragmentation-017.html (live test) (source)
- subgrid-gap-decorations-fragmentation-018.html (live test) (source)
Gap decorations are assigned after collapsed gutter has been applied. A given set of collapsed gutters consume exactly one gap decoration; the next gap decoration is applied to the next gutter (or set of collapsed gutters). Therefore, collapsed gutters are treated as a single gutter for decoration purposes.
3.1.2. Gap decoration segments
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.
- Let S, the collection of gap decoration segments for G, be an empty list.
- Let endpoints be the list of segment endpoints that fall along the centerline of G, ordered from start to end.
- Let starts be an empty stack.
-
For each segment endpoint a in endpoints:
- If a is a start segment endpoint, push a onto starts.
-
If a is an end segment endpoint:
-
If starts is not empty:
- Pop the topmost start segment endpoint b from starts.
- Create a new gap decoration segment from b to a, and append it to S.
- Otherwise, there is no matching start segment endpoint for a; ignore a.
-
If starts is not empty:
Note: In the end, there may remain ignored segment endpoints. These result in negative gap decoration segments. These are segments that would end up overlapping with other gap decoration segments, as a result these are purposefully ignored and no decoration is painted for them. See below for examples.
In this example there is one pair of ignored segment endpoints (which form a negative gap decoration segment). These are marked with green and black crosses, these used to be a end segment endpoint and start segment endpoint respectively. Note that no decoration will be painted for these segments, so we don’t see any blue rectangle between these two points.
In this example there is one pair of ignored segment endpoints (which form a negative gap decoration segment). These are marked with green and black crosses, these used to be a end segment endpoint and start segment endpoint respectively. Note that no decoration will be painted for these segments, so we don’t see any blue rectangle between these two points.
3.2. Breaking gap decorations into segments: The column-rule-break, row-rule-break, and rule-break properties
| Name: | column-rule-break, row-rule-break |
|---|---|
| Value: | none | spanning-item | intersection |
| Initial: | spanning-item |
| 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 |
Sets 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 pairs of gap decoration endpoints.
- 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.
- spanning-item
- Gap decorations start and end at visible "T" intersections but continue through visible "cross" intersections.
- intersection
- Gap decorations start and end at visible "T" and "cross" intersections.
| 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 |
Sets the column-rule-break and row-rule-break properties to the same value.
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)
- 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)
- rule-break-computed.html (live test) (source)
- rule-break-invalid.html (live test) (source)
- rule-break-shorthand.html (live test) (source)
- rule-break-valid.html (live test) (source)
3.2.1. Determining Candidate Gap Segments From Break Rules
Recall that a gap decoration segment, s, can be represented 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.
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.
Define an operation UNION(s1, s2) which updates s1 such that: s1 = [s1.start, s2.end]
For two adjacent segments s and t (where t begins where s ends), UNION(s, t) is flanked by spanning items if spanning items exist on opposing sides of the segments.
- Let S be the list of segments for the given gap, ordered from start to end along the gap’s axis.
- Let C be an empty list of segments.
- Let break be the used value of either column-rule-break or row-rule-break, whichever applies to the gap.
- If S is empty, return C.
-
If break is none:
- Let s be the first segment in S.
- Let last be the last segment in S.
- UNION(s, last)
- Append s to C
- Return C.
- Remove the first segment from S. Let s be that segment.
- If s’s endpoints are discontiguous, go back to step 4.
-
If S is not empty:
- Let next be the first segment in S.
- Let candidate be a copy of s, then UNION(candidate, next)
- If candidate’s endpoints are discontiguous, go to step 9.
- If break is intersection and candidate is not flanked by spanning items, go to step 9.
- Remove the first segment from S.
- UNION(s, next)
- Go back to step 8.
- Append s to C.
- Go back to step 4.
The following examples illustrate various settings for the *-rule-break properties. To make the differences more apparent, the *-rule-*-inset properties are set to 0 and *-rule-visibility-items is set to all.
.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;
rule-inset: 0px;
}
.break-spanning-item-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: spanning-item;
rule-inset: 0px;
}
.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;
rule-inset: 0px;
}
.break-none-flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
row-rule: 6px solid red;
column-rule: 6px solid blue;
rule-break: none;
rule-inset: 0px;
}
Note: Because flexbox has no concept of spanning items, spanning-item on a flexbox has the same effect as none.
.break-intersection-flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
width: 500px;
gap: 20px;
row-rule: 6px solid red;
column-rule: 6px solid blue;
rule-break: intersection;
rule-inset: 0px;
}
3.3. Painting Gap Decorations with Visibility Rules
| Name: | column-rule-visibility-items, row-rule-visibility-items |
|---|---|
| Value: | all | around | between |
| Initial: | all |
| Applies to: | grid containers |
| Inherited: | no |
| Percentages: | n/a |
| Computed value: | as specified |
| Canonical order: | per grammar |
| Animation type: | discrete |
These properties control whether a candidate gap decoration segment is painted in portions of gutters adjacent to empty cells.
- all
- Paint decorations in all gap segments, regardless of whether cells are occupied. This is the initial value.
- around
- Paint decorations in a gap segment if at least one of the two cells adjacent to that segment contains an item.
- between
- Paint decorations in a gap segment if both of the two cells adjacent to that segment contain items.
| Name: | rule-visibility-items |
|---|---|
| Value: | <'column-rule-visibility-items'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-visibility-items and row-rule-visibility-items |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-visibility-items and row-rule-visibility-items properties to the same value.
TODO: FIX: SAM ADD WPT LINKS HERE.
- Let S be the list of constructed segments for this gap, ordered from start to end along the gap’s axis. (From § 3.1.2 Gap decoration segments)
- Let C be the list of candidate segments for this gap, ordered from start to end along the gap’s axis. (From § 3.2.1 Determining Candidate Gap Segments From Break Rules)
- Let vis be the used value for either column-rule-visibility-items or row-rule-visibility-items, whichever applies to the gap.
- Let P be an empty list of segments to be painted.
- If C is empty, return P.
- Remove the first segment from C. Let c be that segment.
-
If vis is all:
- Adjust c’s endpoints by applying endpoint offsets (see § 3.3.1 Adjusting Endpoints When Appending)
- Append c to P.
- Go back to step 5.
- Let current be null.
- Let seg be the constructed segment in S whose start corresponds to c.start.
-
Let (cellA, cellB) be the two cells adjacent to seg.
- Let occupiedA be true if cellA contains an item, false otherwise.
- Let occupiedB be true if cellB contains an item, false otherwise.
- Determine if seg is visible:
-
If seg is not visible:
-
If current is not null:
- Adjust current’s endpoints by applying endpoint offsets (see § 3.3.1 Adjusting Endpoints When Appending)
- Append current to P.
- Set current to null.
-
If current is not null:
-
Otherwise (seg is visible):
- If current is null, set current to seg.
- Otherwise, UNION(current, seg).
-
If seg.end is equal to c.end:
-
If current is not null:
- Adjust current’s endpoints by applying endpoint offsets (see § 3.3.1 Adjusting Endpoints When Appending)
- Append current to P.
- Go back to step 5.
-
If current is not null:
- Set seg to be the next constructed segment in S (the one that immediately follows seg in gap-axis order).
- Go back to step 10.
3.3.1. Adjusting Endpoints When Appending
Given a segment s = [start, end], when appending s to the list of segments to be painted in the above algorithms:
- Compute the offset for start within gap. Offset start by the result, in the forward direction along gap’s axis.
- Compute the offset for end within gap. Offset end by the result, in the reverse direction along gap’s axis.
- Replace s with the adjusted [start, end].
TODO: FIX: SAM ADD EXAMPLE ILLUSTRATING THIS VISIBILITY RULES.
3.4. Adjusting gap segment endpoints: The rule-inset properties
| Name: | column-rule-edge-inset-start, column-rule-edge-inset-end, row-rule-edge-inset-start, row-rule-edge-inset-end |
|---|---|
| Value: | auto | <length-percentage> |
| Initial: | auto |
| 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 |
| Name: | column-rule-interior-inset-start, column-rule-interior-inset-end, row-rule-interior-inset-start, row-rule-interior-inset-end |
|---|---|
| Value: | auto | <length-percentage> |
| Initial: | auto |
| 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 |
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 value of 0 places the gap decoration start and end points exactly on the [start segment endpoint=] and end segment endpoint, respectively, of the gap decoration segment. For the interior properties, because percentages refer to the crossing gap width, a value of -50% places the gap decoration endpoint exactly in the middle of the adjoining intersection.
- auto
- The used value of auto is 0 for edge properties and -50% for interior properties.
An edge segment endpoint is any segment endpoint at the content edges of the container.
An interior segment endpoint is any segment endpoint that is not an edge segment endpoint.
A given start segment endpoint and end segment endpoint can be either an edge segment endpoint or an interior segment endpoint.
These properties control the behavior for any start segment endpoint that is an edge segment endpoint, while the column-rule-edge-inset-end and row-rule-edge-inset-end properties control the behavior for any end segment endpoint that is an edge segment endpoint. Positive values recede inwards from the content edge, while negative values extend outwards, beyond the container’s content bounds.
The column-rule-interior-inset-start and row-rule-interior-inset-start properties control the behavior for any start segment endpoint that is an interior segment endpoint, while the column-rule-interior-inset-end and row-rule-interior-inset-end properties control the behavior for any end segment endpoint that is an interior segment endpoint. Positive values recede away from the segment endpoint, while negative values extend beyond it.
| Name: | column-rule-edge-inset, row-rule-edge-inset |
|---|---|
| Value: | <length-percentage> [ <length-percentage> ]? |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-edge-inset-start, column-rule-interior-inset-start, row-rule-edge-inset-end, and row-rule-interior-inset-end |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-edge-inset-start and column-rule-edge-inset-end properties to the specified values. Similarly, sets the row-rule-edge-inset-start and row-rule-edge-inset-end properties to the specified values.
| Name: | column-rule-interior-inset, row-rule-interior-inset |
|---|---|
| Value: | <length-percentage> [ <length-percentage> ]? |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-edge-inset-start, column-rule-interior-inset-start, row-rule-edge-inset-end, and row-rule-interior-inset-end |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-interior-inset-start and column-rule-interior-inset-end properties to the specified values. Similarly, sets the row-rule-interior-inset-start and row-rule-interior-inset-end properties to the specified values.
| Name: | rule-edge-inset |
|---|---|
| Value: | <'column-rule-edge-inset'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-edge-inset and row-rule-edge-inset |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-edge-inset and row-rule-edge-inset properties to the same value.
| Name: | rule-interior-inset |
|---|---|
| Value: | <'column-rule-interior-inset'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-interior-inset and row-rule-interior-inset |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-interior-inset and row-rule-interior-inset properties to the same value.
| Name: | column-rule-inset, row-rule-inset |
|---|---|
| Value: | <length-percentage> <length-percentage>? [/ <length-percentage> <length-percentage>?]? |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-edge-inset, column-rule-interior-inset, row-rule-edge-inset, and row-rule-interior-inset |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
| Name: | rule-inset |
|---|---|
| Value: | <'column-rule-inset'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-inset and row-rule-inset |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-inset and row-rule-inset properties to the same value. Syntax is as follows:
edge-start edge-end? [/ interior-start interior-end?]?where each of edge-start, edge-end, interior-start, and interior-end are <length-percentage> values.
| Name: | column-rule-inset-start, row-rule-inset-start |
|---|---|
| Value: | auto | <length-percentage> |
| Initial: | see individual properties |
| Applies to: | column-rule-edge-inset-start and column-rule-interior-inset-start for column-rule-inset-start, row-rule-edge-inset-start and row-rule-interior-inset-start for row-rule-inset-start |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-edge-inset-start and column-rule-interior-inset-start properties to the same value. Similarly, sets the row-rule-edge-inset-start and row-rule-interior-inset-start properties to the same value.
| Name: | column-rule-inset-end, row-rule-inset-end |
|---|---|
| Value: | auto | <length-percentage> |
| Initial: | see individual properties |
| Applies to: | column-rule-edge-inset-end and column-rule-interior-inset-end for column-rule-inset-end, row-rule-edge-inset-end and row-rule-interior-inset-end for row-rule-inset-end |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-edge-inset-end and column-rule-interior-inset-end properties to the same value. Similarly, sets the row-rule-edge-inset-end and row-rule-interior-inset-end properties to the same value.
| Name: | rule-inset-start |
|---|---|
| Value: | <'column-rule-inset-start'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-inset-start and row-rule-inset-start |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-inset-start and row-rule-inset-start properties to the same value.
| Name: | rule-inset-end |
|---|---|
| Value: | <'column-rule-inset-end'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-inset-end and row-rule-inset-end |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
Sets the column-rule-inset-end and row-rule-inset-end properties to the same value.
.inset-0px {
column-rule-inset: 0px;
column-rule-break: intersection;
}
.inset-negative-5px {
column-rule-inset: -5px;
column-rule-break: intersection;
}
.inset-start-8px-end-0px {
column-rule-inset-start: 8px;
column-rule-inset-end: 0px;
}
.inset-edge-0px-interior-negative-5px {
column-rule-edge-inset: 0px;
column-rule-interior-inset: -5px;
column-rule-break: intersection;
}
.inset-50percent {
column-rule-inset: 50%;
column-rule-break: intersection;
}
.inset-positive-5px {
column-rule-inset: 5px;
column-rule-break: intersection;
}
When considering the segment endpoints within a given gap, each point is assigned a crossing gap width, defined as follows:
- At the content edge of the container
- The crossing gap width is 0.
- At an intersection with another gap
- The crossing gap width is the used value of the column-gap or row-gap property, whichever applies to the intersecting gap.
- Let width be the crossing gap width for point.
- Let inset be the computed value of either column-rule-inset or row-rule-inset, whichever applies to gap. Resolve any percentages in inset against width.
- Let result be width multiplied by 50%. Add inset to result.
- Return result.
For details on how the offset is applied, see § 3.3.1 Adjusting Endpoints When Appending.
Tests
- flex-gap-decorations-011.html (live test) (source)
- flex-gap-decorations-013.html (live test) (source)
- flex-gap-decorations-014.html (live test) (source)
- flex-gap-decorations-029.html (live test) (source)
- flex-gap-decorations-030.html (live test) (source)
- grid-gap-decorations-010.html (live test) (source)
- grid-gap-decorations-011.html (live test) (source)
- grid-gap-decorations-012.html (live test) (source)
- grid-gap-decorations-013.html (live test) (source)
- grid-gap-decorations-014.html (live test) (source)
- grid-gap-decorations-015.html (live test) (source)
- grid-gap-decorations-038.html (live test) (source)
- grid-gap-decorations-052.html (live test) (source)
- grid-gap-decorations-053.html (live test) (source)
- subgrid-gap-decorations-007.html (live test) (source)
- subgrid-gap-decorations-008.html (live test) (source)
- multicol-gap-decorations-008.html (live test) (source)
- multicol-gap-decorations-009.html (live test) (source)
- multicol-gap-decorations-010.html (live test) (source)
- multicol-gap-decorations-011.html (live test) (source)
- multicol-gap-decorations-012.html (live test) (source)
- rule-edge-start-end-inset-computed.html (live test) (source)
- rule-edge-start-end-inset-invalid.html (live test) (source)
- rule-inset-bidirectional-shorthand.html (live test) (source)
- rule-inset-computed.html (live test) (source)
- rule-inset-invalid.html (live test) (source)
- rule-inset-shorthand.html (live test) (source)
- rule-inset-valid.html (live test) (source)
- rule-interior-start-end-inset-computed.html (live test) (source)
- rule-interior-start-end-inset-invalid.html (live test) (source)
3.5. Gap decoration overlap: The rule-overlap property
| Name: | rule-overlap |
|---|---|
| Value: | row-over-column | column-over-row |
| Initial: | row-over-column |
| Applies to: | grid containers, flex containers, and grid lanes containers |
| Inherited: | no |
| Percentages: | n/a |
| Computed value: | as specified |
| Canonical order: | per grammar |
| Animation type: | discrete |
Sets the overlap for gap decorations in two-dimensional containers.
The following examples illustrate adjustment of gap decoration overlap using the rule-overlap property.
.row-over-coulumn {
rule-overlap: row-over-column;
row-rule: 6px solid red;
column-rule: 6px solid blue;
}
rule-overlap: column-over-row; row-rule: 6px solid red; column-rule: 6px solid blue;
Tests
4. Color, style, and width
Property definitions in this section supersede the definitions of properties with the same names in [CSS-MULTICOL-1].
4.1. Gap decoration color: The column-rule-color and row-rule-color properties
| Name: | column-rule-color, row-rule-color |
|---|---|
| Value: | <line-color-list> | <auto-line-color-list> |
| Initial: | currentcolor |
| 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: | repeatable list, see § 4.4.1 Interpolation behavior. |
<line-color-list> = [ <line-color-or-repeat> ]+
<auto-line-color-list> = [ <line-color-or-repeat> ]*
<auto-repeat-line-color>
[ <line-color-or-repeat> ]*
<line-color-or-repeat> = [ <color> | <repeat-line-color> ]
<repeat-line-color> = repeat( [ <integer [1,∞]> ] , [ <color> ]+ )
<auto-repeat-line-color> = repeat( auto , [ <color> ]+ )
- <color>
- Sets the color of gap decorations.
Tests
- gap-decorations-003.html (live test) (source)
- gap-decorations-004.html (live test) (source)
- gap-decorations-010-crash.html (live test) (source)
- grid-gap-decorations-022.html (live test) (source)
- grid-gap-decorations-024.html (live test) (source)
- grid-gap-decorations-025.html (live test) (source)
- grid-gap-decorations-026.html (live test) (source)
- grid-gap-decorations-027.html (live test) (source)
- grid-gap-decorations-028.html (live test) (source)
- grid-gap-decorations-048.html (live test) (source)
- grid-gap-decorations-049.html (live test) (source)
- grid-gap-decorations-050.html (live test) (source)
- grid-gap-decorations-051.html (live test) (source)
- multicol-gap-decorations-019.html (live test) (source)
- gap-decorations-color-computed.html (live test) (source)
- gap-decorations-color-invalid.html (live test) (source)
- gap-decorations-color-valid.html (live test) (source)
4.2. Gap decoration style: The column-rule-style and row-rule-style properties
| Name: | column-rule-style, row-rule-style |
|---|---|
| Value: | <line-style-list> | <auto-line-style-list> |
| Initial: | none |
| 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 |
<line-style-list> = [ <line-style-or-repeat> ]+
<auto-line-style-list> = [ <line-style-or-repeat> ]*
<auto-repeat-line-style>
[ <line-style-or-repeat> ]*
<line-style-or-repeat> = [ <line-style> | <repeat-line-style> ]
<repeat-line-style> = repeat( [ <integer [1,∞]> ] , [ <line-style> ]+ )
<auto-repeat-line-style> = repeat( auto , [ <line-style> ]+ )
These properties set the styles of gap decorations. The <line-style> values are interpreted as in the collapsing border model.
Tests
- flex-gap-decorations-002.html (live test) (source)
- flex-gap-decorations-003.html (live test) (source)
- flex-gap-decorations-004.html (live test) (source)
- flex-gap-decorations-005.html (live test) (source)
- flex-gap-decorations-017.html (live test) (source)
- flex-gap-decorations-018.html (live test) (source)
- grid-gap-decorations-002.html (live test) (source)
- grid-gap-decorations-003.html (live test) (source)
- grid-gap-decorations-004.html (live test) (source)
- grid-gap-decorations-005.html (live test) (source)
- grid-gap-decorations-016.html (live test) (source)
- grid-gap-decorations-017.html (live test) (source)
- grid-gap-decorations-020.html (live test) (source)
- grid-gap-decorations-021.html (live test) (source)
- grid-gap-decorations-039.html (live test) (source)
- gap-decorations-style-computed.html (live test) (source)
- gap-decorations-style-invalid.html (live test) (source)
- gap-decorations-style-valid.html (live test) (source)
4.3. Gap decoration width: The column-rule-width and row-rule-width properties
| Name: | column-rule-width, row-rule-width |
|---|---|
| Value: | <line-width-list> | <auto-line-width-list> |
| Initial: | medium |
| Applies to: | grid containers, flex containers, multicol containers, and grid lanes containers |
| Inherited: | no |
| Percentages: | n/a |
| Computed value: | list of absolute lengths, snapped as a border width |
| Canonical order: | per grammar |
| Animation type: | repeatable list, see § 4.4.1 Interpolation behavior. |
<line-width-list> = [ <line-width-or-repeat> ]+
<auto-line-width-list> = [ <line-width-or-repeat> ]*
<auto-repeat-line-width>
[ <line-width-or-repeat> ]*
<line-width-or-repeat> = [ <line-width> | <repeat-line-width> ]
<repeat-line-width> = repeat( [ <integer [1,∞]> ] , [ <line-width> ]+ )
<auto-repeat-line-width> = repeat( auto , [ <line-width> ]+ )
This property sets the widths of gap decorations. Negative values are not allowed.
Tests
- gap-decorations-009-crash.html (live test) (source)
- grid-gap-decorations-018.html (live test) (source)
- grid-gap-decorations-019.html (live test) (source)
- multicol-gap-decorations-004.html (live test) (source)
- gap-decorations-col-rule-width.html (live test) (source)
- gap-decorations-width-computed.html (live test) (source)
- gap-decorations-width-invalid.html (live test) (source)
- gap-decorations-width-valid.html (live test) (source)
4.4. Lists of values and the repeat() notation
Each of the properties in this section accepts a space-separated list of values. Setting multiple values in this way allows for varying gap decorations within a given container.
column-rule-width: 1px; column-rule-style: solid; column-rule-color: red blue;
Such a list may contain repeat() notations. Similar to CSS Grid Layout 1 § 7.2.3 Repeating Rows and Columns: the repeat() notation, these notations allow a series of gap decorations that exhibit a recurring pattern to be written in a more compact form.
The generic form of the repeat() syntax is, approximately,
repeat( [ <integer [1,∞]> | auto ] , <value>+ )
The first argument to repeat() specifies the number of repetitions.
- <integer>
- Specifies an integer repeater. An integer repeater expands out to the list of values in the second argument, repeated as many times as specified by the first argument.
- auto
-
Specfies an auto repeater.
An auto repeater will be used to fill in values for gaps
that would not otherwise receive values from other parts of the list.
At most one repeat() in a given list of values may be an auto repeater.
Continuing from the previous example, if the author does not know how many columns will be in the final layout, they might instead write:
column-rule-color: gray repeat(auto, red blue) gray;
Which will produce a gray decoration in the first and last column gaps, and alternating red and blue decorations in the in-between column gaps.
The second argument to repeat() is a space-separated list of values that would be accepted by the property in which the repeat() appears.
- Replace any integer repeaters in values with their expanded-out equivalents.
-
If the list contains no auto repeater, then:
- Beginning from the first item in values and the first item in gaps, assign each value to the corresponding gap. If there are fewer values than gaps, repeat beginning from the first item in values, as many times as needed.
- End this algorithm.
- values contains an auto repeater. Let leading count be the number of items in values before the auto repeater. Let trailing count be the number of items in values after the auto repeater.
-
Partition gaps as follows:
- Let leading gaps contain the first leading count items in gaps.
- Let trailing gaps contain the last trailing count items in gaps, excluding any items in leading gaps.
- Let auto gaps contain any items in gaps that are not in either leading gaps or trailing gaps.
- If leading gaps is non-empty, assign gap decoration values to leading gaps using the first leading count items in values.
- If trailing gaps is non-empty, assign gap decoration values to trailing gaps using the first trailing count items in values.
- If auto gaps is non-empty, assign gap decoration values to auto gaps using the list of values in the second argument of the auto repeater.
4.4.1. Interpolation behavior
When interpolating repeat() values, or lists of values for rule-color or rule-width, the interpolation proceeds in two steps:- Expansion: Expand any integer repeater into its equivalent list of values.
- List Interpolation: Apply the repeatable list interpolation algorithm to the expanded lists, interpolating each item against its counterpart.
Interpolation of the above values would result in expansion of the "from" and "to" values to create lists of equal lengths:@keyframes example{ from{ column-rule-width : 10 px ; } to{ column-rule-width : 20 px 40 px ; } }
From: 10px 10px At 50%: 15px 25px To: 20px 40px
Interpolation of the above values would result in expansion of the "from" and "to" values to create lists of equal lengths:@keyframes example{ from{ column-rule-width : repeat ( 2 , 5 px 10 px ); } to{ column-rule-width : repeat ( 2 , 15 px 20 px ); } }
From: 5px 10px 5px 10px At 50%: 10px 15px 10px 15px To: 15px 20px 15px 20px
Interpolation of the above values would result in expansion of the "from" and "to" values to create lists of equal lengths:@keyframes example{ from{ column-rule-width : repeat ( 2 , 10 px 20 px ); } to{ column-rule-width : 20 px ; } }
From: 10px 20px 10px 20px At 50%: 15px 20px 15px 20px To: 20px 20px 20px 20px
Interpolation of the above values would result in expansion of the "from" and "to" values to create lists of equal lengths:@keyframes example{ from{ column-rule-width : repeat ( 2 , 10 px 20 px ); } to{ column-rule-width : 20 px 30 px ; } }
From: 10px 20px 10px 20px At 50%: 15px 25px 15px 25px To: 20px 30px 20px 30px
4.4.1.1. Lists with Auto Repeaters
When either of the lists we are interpolating between (from and to) include an auto repeater:
-
Split each of from and to into segments, similar to how we assign gap decoration values:
- Let leading values be the values before the auto repeater.
- Let trailing values be the values after the auto repeater.
- Let auto values be the values inside the auto repeater.
- If only one of from or to contains an auto-repeater, we fall back to discrete interpolation.
- Expand any integer repeaters on each segment.
- If the length of leading values in from and leading values in to don’t match, we fall back to discrete interpolation. If the length of trailing values in from and trailing values in to don’t match, we fall back to discrete interpolation.
- When both from and to contain auto-repeaters, and the length of their segments match as described above, apply repeatable list interpolation to the lists of values in each auto values.
Length of the leading values and trailing values across from and to match, so we can apply the repeatable list algorithm to each segment.@keyframes example{ from{ column-rule-width : 10 px repeat ( auto, 20 px ) 30 px } to{ column-rule-width : 20 px repeat ( auto, 40 px ) 40 px } }
From: 10px repeat(auto, 20px) 30px At 50%: 15px repeat(auto, 30px) 35px To: 20px repeat(auto, 40px) 40px
Length of the leading values and trailing values across from and to match, so we can apply the repeatable list algorithm to each segment.@keyframes example{ from{ column-rule-width : 10 px 20 px repeat ( auto, 20 px ) 30 px } to{ column-rule-width : 20 px 30 px repeat ( auto, 40 px 50 px ) 40 px } }
From: 10px 20px repeat(auto, 20px 20px) 30px At 50%: 15px 25px repeat(auto, 30px 35px) 35px To: 20px 30px repeat(auto, 40px 50px) 40px
Length of the from leading values and to leading values don’t match, so we fall back to discrete interpolation.@keyframes example{ from{ column-rule-width : 10 px repeat ( auto, 20 px ) } to{ column-rule-width : 20 px 30 px repeat ( auto, 40 px 50 px ) } }
Length of the from trailing values and to trailing values don’t match, so we fall back to discrete interpolation.@keyframes example{ from{ column-rule-width : 10 px repeat ( auto, 20 px ) 30 px } to{ column-rule-width : 20 px repeat ( auto, 40 px ) 40 px 50 px } }
Only from contains an auto repeater, so we fall back to discrete interpolation.@keyframes example{ from{ column-rule-width : 10 px repeat ( auto, 20 px ) 30 px } to{ column-rule-width : 20 px } }
Tests
- column-rule-outset-interpolation.html (live test) (source)
- gap-decorations-color-neutral-keyframe-001.html (live test) (source)
- gap-decorations-color-neutral-keyframe-002.html (live test) (source)
- gap-decorations-color-neutral-keyframe-003.html (live test) (source)
- gap-decorations-color-neutral-keyframe-004.html (live test) (source)
- gap-decorations-color-neutral-keyframe-005.html (live test) (source)
- gap-decorations-outset-neutral-keyframe-001.html (live test) (source)
- gap-decorations-outset-neutral-keyframe-002.html (live test) (source)
- gap-decorations-width-neutral-keyframe-001.html (live test) (source)
- gap-decorations-width-neutral-keyframe-002.html (live test) (source)
- gap-decorations-width-neutral-keyframe-003.html (live test) (source)
- gap-decorations-width-neutral-keyframe-004.html (live test) (source)
- gap-decorations-width-neutral-keyframe-005.html (live test) (source)
- row-rule-color-interpolation.html (live test) (source)
- row-rule-outset-interpolation.html (live test) (source)
- row-rule-width-interpolation.html (live test) (source)
- rule-color-interpolation-conversion-001.html (live test) (source)
- rule-color-interpolation-conversion-002.html (live test) (source)
- rule-color-interpolation-conversion-crash.html (live test) (source)
- rule-color-interpolation-multiple-values-001.html (live test) (source)
- rule-color-interpolation-repeaters-001.html (live test) (source)
- rule-width-interpolation-conversion-001.html (live test) (source)
- rule-width-interpolation-conversion-002.html (live test) (source)
- rule-width-interpolation-multiple-values-001.html (live test) (source)
- rule-width-interpolation-multiple-values-002.html (live test) (source)
- rule-width-interpolation-repeaters.html (live test) (source)
4.5. Gap decoration shorthands: The column-rule and row-rule properties
| Name: | column-rule, row-rule |
|---|---|
| Value: | <gap-rule-list> | <gap-auto-rule-list> |
| Initial: | see individual properties |
| Applies to: | see individual properties |
| Inherited: | see individual properties |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
<gap-rule-list> = <gap-rule-or-repeat>#
<gap-auto-rule-list> = <gap-rule-or-repeat>#? ,
<gap-auto-repeat-rule> ,
<gap-rule-or-repeat>#?
<gap-rule-or-repeat> = <gap-rule> | <gap-repeat-rule>
<gap-repeat-rule> = repeat( <integer [1,∞]> , <gap-rule># )
<gap-auto-repeat-rule> = repeat( auto , <gap-rule># )
<gap-rule> = <line-width> || <line-style> || <color>
These shorthands set the corresponding width, style, and color properties as a set.
Tests
4.6. Bi-directional gap decoration shorthands: The rule-color, rule-style, rule-width, and rule properties
| Name: | rule-color |
|---|---|
| Value: | <'column-rule-color'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-color and row-rule-color |
| Inherited: | no |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
| Name: | rule-style |
|---|---|
| Value: | <'column-rule-style'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-style and row-rule-style |
| Inherited: | no |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
| Name: | rule-width |
|---|---|
| Value: | <'column-rule-width'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule-width and row-rule-width |
| Inherited: | no |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
| Name: | rule |
|---|---|
| Value: | <'column-rule'> |
| Initial: | see individual properties |
| Applies to: | Same as column-rule and row-rule |
| Inherited: | no |
| Percentages: | see individual properties |
| Computed value: | see individual properties |
| Animation type: | see individual properties |
| Canonical order: | per grammar |
These shorthands set the corresponding column and row properties to the same values.
Tests
- flex-gap-decorations-019.html (live test) (source)
- gap-decorations-bidirectional-shorthands.html (live test) (source)
- gap-decorations-rule-initial-value-crash.html (live test) (source)
- gap-decorations-rule-shorthand-computed.html (live test) (source)
- gap-decorations-rule-shorthand-invalid.html (live test) (source)
- gap-decorations-rule-shorthand-valid.html (live test) (source)
- gap-decorations-rule-shorthand.html (live test) (source)
5. Privacy Considerations
No new privacy considerations have been reported on this specification.
6. Security Considerations
No new security considerations have been reported on this specification.
7. Acknowledgements
This specification is made possible by contributions and feedback from many people, including: Ahmad Shadeed, Alison Maher, Benoît Rouleau, Elika Etemad, Ian Kilpatrick, Javier Contreras Tenorio, Josh Tumath, Kurt Catti-Schmidt, Lea Verou, Oliver Williams, Rachel Andrew, Sam Davis Omekara Jr., Sebastian Zartner, Tab Atkins-Bittner, and the CSS Working Group members. Special thanks to Mats Palmgren who drafted an initial proposal for Gap Decorations.
8. Changes
8.1. Changes since the 17 April 2025 Working Draft
- Specified the behavior when gaps are coincident due to track collapsing. (Issue 11814)
- Added links to WPT suite.
- Updated rule-paint-order to rule-overlap. (Issue 12540)
- Updated the definition for intersections to use gutter. (Issue 12084)
- Updated trailing gap decoration assignment to use values in forward order. (Issue 12527)
- Specified the interpolation behavior for values which may contain repeaters. (Issue 12431)
- Removed the special case of column-rule-width having a computed value of 0 when column-rule-style is none or . (Issue 11494)
- Updated `*-outset` to `*-inset` and introduced related properties. (Issue 12603, Issue 12848, Issue 8402)
- Added a paragraph clarifying that gap decorations are not drawn where gaps are suppressed due to fragment breaks.
- Corrected syntax errors for the inset shorthands.
- Updated the behavior for when gaps are coincident due to track collapsing. (Issue 11814)