Title: CSS Gap Decorations Module Level 1
Shortname: css-gaps
Level: 1
Status: ED
Prepare for TR: no
Group: csswg
Work Status: revising
Repository: w3c/csswg-drafts
URL: https://drafts.csswg.org/css-gaps-1/
TR: https://www.w3.org/TR/css-gaps-1/
Previous Version: https://www.w3.org/TR/2026/WD-css-gaps-1-20260227/
Previous Version: https://www.w3.org/TR/2025/WD-css-gaps-1-20250417/
Editor: Kevin Babbitt, Microsoft, https://github.com/kbabbitt, w3cid 124689
Abstract: This module introduces several properties to add row and column gap decorations to container layout types such as grid and flex.
WPT Path Prefix: css/css-gaps/
WPT Display: open
This section is not normative.
[[CSS-MULTICOL-1#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.
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.
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:
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]].
In the main axis
(e.g. 'column-gap' in a ''flex-flow/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 ''flex-flow/row'' flex container),
[=gap=] ([=row gap=]) refers to the [=gutter=] between adjacent flex lines.
[=row gaps=] and [=column gaps=]
refer to the [=gutters=] between grid rows and grid columns,
respectively.
See [[css-grid-1#gutters]] for precise details.
Note: As specified in [[CSS-ALIGN-3#column-row-gap]],
additional spacing between items added by 'justify-content' and 'align-content'
is included in [=gap=] size.
[=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.
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 and text direction into account when determining the meanings of these terms.
For examples, see:
[[CSS-MULTICOL-2#the-multi-column-model]],
[[CSS-FLEXBOX-1#flex-direction-property]],
and
[[CSS-GRID-1#grid-concepts]].
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=].
Geometry
[=Gap decorations=] are painted within a [=gap=] as one or more [=gap decoration segments=].
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=].
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.
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.
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.
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.
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|:
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 ''column-rule-break/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 a segment|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.
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.
Name: rule-break
Value: <<'column-rule-break'>>
Applies to: Same as 'column-rule-break' and 'row-rule-break'
This [=shorthand property=] sets 'column-rule-break' and 'row-rule-break' to the same value.
parsing/rule-break-computed.html
parsing/rule-break-invalid.html
parsing/rule-break-shorthand.html
parsing/rule-break-valid.html
The following examples illustrate various settings for the *-rule-break properties.
Multicol [=gap decorations=] with rule-break set to ''column-rule-break/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''.
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:
[=Gap decorations=] in adjacent flex lines are separate from each other even if the gaps happen to line up.
''column-rule-break/none'' would have the same visual effect as ''column-rule-break/normal''.
Flexbox gap decorations contained within each [=gap decoration segment=].
Adjusting gap decoration endpoints: The 'rule-inset' properties
Name: column-rule-edge-inset-start, column-rule-edge-inset-end, column-rule-interior-inset-start, column-rule-interior-inset-end, row-rule-edge-inset-start, row-rule-edge-inset-end, row-rule-interior-inset-start, row-rule-interior-inset-end
Value: <>
Initial: ''0''
Applies to: grid containers, flex containers, multicol containers, and grid lanes containers
Inherited: no
Percentages: refer to the crossing gap width
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.
An edge segment endpoint is any [=segment endpoint=] created at the content edges of the container.
An interior segment endpoint is any [=segment endpoint=] created at a [=gap junction=].
Percentages are resolved against the crossing gap width, defined as follows:
Edge segment endpoints
The [=crossing gap width=] is ''0''.
Interior segment endpoints
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=]).
Note: Typically, this will be the used value of the 'column-gap' or 'row-gap' property,
whichever applies to the intersecting or abutting gap,
plus any additional spacing added due to 'justify-content' or 'align-content'.
However, in cases where [=gaps=] intersect or abut one another at overlapping intervals,
the [=crossing gap width=] will be determined by the union of such intervals.
See this example for one such case.
The 'column-rule-edge-inset-start' and 'row-rule-edge-inset-start' properties apply to [=start segment endpoints=] that are [=edge segment endpoints=].
The 'column-rule-interior-inset-start' and 'row-rule-interior-inset-start' properties apply to [=start segment endpoints=] that are [=interior segment endpoints=].
For these properties, positive values offset in the [=end=] direction, and negative values offset in the [=start=] direction, along the axis of the gap.
The 'column-rule-edge-inset-end' and 'row-rule-edge-inset-end' properties apply to [=end segment endpoints=] that are [=edge segment endpoints=].
The 'column-rule-interior-inset-end' and 'row-rule-interior-inset-end' properties apply to [=end segment endpoints=] that are [=interior segment endpoints=].
For these properties, positive values offset in the [=start=] direction, and negative values offset in the [=end=] direction, along the axis of the gap.
A start inset of ''8px'' recedes the starts of [=gap decorations=],
while an end inset of ''0px'' aligns the ends of [=gap decorations=] with content edges.
Name: column-rule-inset-start, column-rule-inset-end, row-rule-inset-start, row-rule-inset-end
Value: <>
Applies to: Same as 'column-rule-edge-inset-start', 'column-rule-interior-inset-start', 'column-rule-edge-inset-end', 'column-rule-interior-inset-end', 'row-rule-edge-inset-start', 'row-rule-interior-inset-start', 'row-rule-edge-inset-end', and 'row-rule-interior-inset-end'
These [=shorthand properties=] set the corresponding ''-edge-'' and ''-interior-'' properties to the same value.
For example, 'column-rule-inset-start' sets both 'column-rule-edge-inset-start' and 'column-rule-interior-inset-start' to the same value.
Name: rule-inset-start
Value: <<'column-rule-inset-start'>>
Applies to: Same as 'column-rule-inset-start' and 'row-rule-inset-start'
This [=shorthand property=] sets 'column-rule-inset-start' and 'row-rule-inset-start' to the same value.
Name: rule-inset-end
Value: <<'column-rule-inset-end'>>
Applies to: Same as 'column-rule-inset-end' and 'row-rule-inset-end'
This [=shorthand property=] sets 'column-rule-inset-end' and 'row-rule-inset-end' to the same value.
parsing/rule-inset-start-end-bidirectional-shorthand.html
parsing/rule-inset-start-end-computed.html
parsing/rule-inset-start-end-invalid.html
parsing/rule-inset-start-end-shorthand.html
parsing/rule-inset-start-end-valid.html
''-edge-'' and ''-interior-'' shorthands
These shorthands allow authors to achieve different treatments at edge versus interior intersections.
An interior inset of ''-5px'' extends the endpoints of interior gap decorations
slightly beyond the edges of adjacent items. An edge inset of ''0px'' aligns the endpoints of edge gap decorations
with the content edges.
Name: column-rule-edge-inset, column-rule-interior-inset, row-rule-edge-inset, row-rule-interior-inset
Value: <> [ <> ]?
Applies to: Same as 'column-rule-edge-inset-start', 'column-rule-edge-inset-end', 'column-rule-interior-inset-start', 'column-rule-interior-inset-end', 'row-rule-edge-inset-start', 'row-rule-edge-inset-end', 'row-rule-interior-inset-start', and 'row-rule-interior-inset-end'
These shorthands set the corresponding ''-start'' and ''-end'' properties.
For example, 'column-rule-edge-inset' sets both 'column-rule-edge-inset-start' and 'column-rule-edge-inset-end'.
If one value is specified, both properties are set to that value.
If two values are specified, ''-start'' is set to the first and ''-end'' is set to the second.
Name: rule-edge-inset
Value: <<'column-rule-edge-inset'>>
Applies to: Same as 'column-rule-edge-inset' and 'row-rule-edge-inset'
This [=shorthand property=] sets 'column-rule-edge-inset' and 'row-rule-edge-inset' to the same value.
Name: rule-interior-inset
Value: <<'column-rule-interior-inset'>>
Applies to: Same as 'column-rule-interior-inset' and 'row-rule-interior-inset'
This [=shorthand property=] sets 'column-rule-interior-inset' and 'row-rule-interior-inset' to the same value.
parsing/rule-edge-inset-bidirectional-shorthand.html
parsing/rule-edge-interior-inset-computed.html
parsing/rule-edge-interior-inset-invalid.html
parsing/rule-edge-interior-inset-shorthand.html
parsing/rule-edge-interior-inset-valid.html
parsing/rule-interior-inset-bidirectional-shorthand.html
Universal shorthands
These shorthands allow authors to achieve uniform treatments throughout a container.
An inset of ''-50%'' extends each end of a gap decoration
halfway into its intersection.
Neighboring gap decorations "meet in the middle" to create a continuous line.
Note that at the edges of the container, the crossing gap width is defined to be ''0'',
so the inset value of ''-50%'' resolves to ''0''
and thus the gap decoration does not extend beyond the bounds of the container.
(Contrast with the previous example, which specified an inset in ''px'' units.)
Name: column-rule-inset, row-rule-inset
Value: <<'column-rule-edge-inset'>> [ / <<'column-rule-interior-inset'>> ]?
Applies to: Same as 'column-rule-edge-inset', 'column-rule-interior-inset', 'row-rule-edge-inset', and 'row-rule-interior-inset'
These shorthands set the corresponding edge and interior start and end values.
The order of values is:
If the interior values are omitted, they are copied from the edge values.
Any omitted end value is copied from the corresponding start value.
Name: rule-inset
Value: <<'column-rule-inset'>>
Applies to: Same as 'column-rule-inset' and 'row-rule-inset'
This [=shorthand property=] sets 'column-rule-inset' and 'row-rule-inset' to the same value.
parsing/rule-inset-bidirectional-shorthand.html
parsing/rule-inset-computed.html
parsing/rule-inset-invalid.html
parsing/rule-inset-shorthand.html
parsing/rule-inset-valid.html
Gap decoration visibility: The 'rule-visibility-items' properties
Name: column-rule-visibility-items, row-rule-visibility-items
Value: ''all'' | ''around'' | ''between'' | ''normal''
Initial: ''normal''
Applies to: [=grid containers=] and [=multicol containers=]
Inherited: no
Computed value: as specified
Animation type: discrete
These properties control whether a [=gap decoration segment=] is painted
in portions of [=gaps=] adjacent to empty areas.
all
Paint decorations in all gap segments, regardless of whether adjacent items are present.
around
Paint decorations in a gap segment if at least one of the two adjacent areas is occupied by an item.
between
Paint decorations in a gap segment if both adjacent areas are occupied by items.
normal
Behavior depends on the type of container.
[=Grid containers=]
Behaves the same as ''all''.
[=Multicol containers=]
On 'column-rule-visibility-items', behaves the same as ''column-rule-visibility-items/between''.
On 'row-rule-visibility-items', behaves the same as ''row-rule-visibility-items/all''.
Name: rule-visibility-items
Value: <<'column-rule-visibility-items'>>
Applies to: Same as 'column-rule-visibility-items' and 'row-rule-visibility-items'
This [=shorthand property=] sets 'column-rule-visibility-items' and 'row-rule-visibility-items' to the same value.
These properties set the widths of gap decorations. Negative values are not allowed.
Name: rule-width
Value: <<'column-rule-width'>>
Inherited: no
Applies to: Same as 'column-rule-width' and 'row-rule-width'
This [=shorthand property=] sets 'column-rule-width' and 'row-rule-width' to the same value.
agnostic/gap-decorations-009-crash.html
grid/grid-gap-decorations-018.html
grid/grid-gap-decorations-019.html
multicol/multicol-gap-decorations-004.html
parsing/gap-decorations-col-rule-width.html
parsing/gap-decorations-width-computed.html
parsing/gap-decorations-width-invalid.html
parsing/gap-decorations-width-valid.html
Gap decoration shorthands: The 'column-rule', 'row-rule', and 'rule' properties
These [=shorthand properties=] set values for the
'column-rule-width', 'column-rule-style', and 'column-rule-color' properties,
or the 'row-rule-width', 'row-rule-style', and 'row-rule-color' properties,
respectively.
Name: rule
Value: <<'column-rule'>>
Inherited: no
Applies to: Same as 'column-rule' and 'row-rule'
This [=shorthand property=] sets 'column-rule' and 'row-rule' to the same values.
flex/flex-gap-decorations-019.html
parsing/gap-decorations-bidirectional-shorthands.html
parsing/gap-decorations-rule-initial-value-crash.html
parsing/gap-decorations-rule-shorthand-computed.html
parsing/gap-decorations-rule-shorthand-invalid.html
parsing/gap-decorations-rule-shorthand-valid.html
parsing/gap-decorations-rule-shorthand.html
Lists of values and the ''repeat()'' notation
Each of the properties in this section accepts a comma-separated list of values.
Setting multiple values in this way allows for varying gap decorations within a given container.
An author might specify alternating red and blue column rules as follows:
Such a list may contain repeat() notations.
Similar to [[css-grid-1#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( [ <> | auto ] , <value># )
The first argument to ''repeat()'' specifies the number of repetitions.
<>
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.
Specifies 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:
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 comma-separated list of values
that would be accepted by the property in which the ''repeat()'' appears.
Assigning gap decoration values to gaps
Gap decorations are [=assigned gap decoration values|assigned=] after [=collapsed gutter|gutter collapsing=] 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 [=gap=] for decoration purposes.
To assign gap decoration values to a list of |gaps| using a list of |values|:
Replace any integer repeaters in |values| with their expanded-out equivalents.
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|.
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.
@keyframes example {
from { column-rule-width: 10px; }
to { column-rule-width: 20px, 40px; }
}
Interpolation of the above values would result in expansion of the
"from" and "to" values to create lists of equal lengths:
From: 10px, 10px
At 50%: 15px, 25px
To: 20px, 40px
@keyframes example {
from { column-rule-width: repeat(2, 5px, 10px); }
to { column-rule-width: repeat(2, 15px, 20px); }
}
Interpolation of the above values would result in expansion of the
"from" and "to" values to create lists of equal lengths:
From: 5px, 10px, 5px, 10px
At 50%: 10px, 15px, 10px, 15px
To: 15px, 20px, 15px, 20px
@keyframes example {
from { column-rule-width: repeat(2, 10px, 20px); }
to { column-rule-width: 20px; }
}
Interpolation of the above values would result in expansion of the
"from" and "to" values to create lists of equal lengths:
From: 10px, 20px, 10px, 20px
At 50%: 15px, 20px, 15px, 20px
To: 20px, 20px, 20px, 20px
@keyframes example {
from { column-rule-width: repeat(2, 10px, 20px); }
to { column-rule-width: 20px, 30px; }
}
Interpolation of the above values would result in expansion of the
"from" and "to" values to create lists of equal lengths:
From: 10px, 20px, 10px, 20px
At 50%: 15px, 25px, 15px, 25px
To: 20px, 30px, 20px, 30px
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|.
@keyframes example {
from { column-rule-width: 10px, repeat(auto, 20px), 30px }
to { column-rule-width: 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.
From: 10px, repeat(auto, 20px), 30px
At 50%: 15px, repeat(auto, 30px), 35px
To: 20px, repeat(auto, 40px), 40px
@keyframes example {
from { column-rule-width: 10px, 20px, repeat(auto, 20px), 30px }
to { column-rule-width: 20px, 30px, repeat(auto, 40px, 50px), 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.
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
@keyframes example {
from { column-rule-width: 10px, repeat(auto, 20px) }
to { column-rule-width: 20px, 30px, repeat(auto, 40px, 50px) }
}
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: 10px, repeat(auto, 20px), 30px }
to { column-rule-width: 20px, repeat(auto, 40px), 40px, 50px }
}
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: 10px, repeat(auto, 20px), 30px }
to { column-rule-width: 20px }
}
Only |from| contains an auto repeater, so we fall back to [=discrete=] interpolation.
The 'column-rule', 'row-rule', and 'rule' shorthands
are serialized from component longhand properties
only if the longhand properties are [=repeater aligned=].
If the longhand properties are not [=repeater aligned=],
the shorthand serializes as an empty string.
Let |W|, |S| and |C| be the values for the width, style, and color
longhand properties respectively. Recall that each is a list of
items, where an item is either a single value or a ''repeat()'' notation.
The longhand properties are repeater aligned
if and only if all of the following are true:
|W|, |S| and |C| all have the same number of items.
For each item index |i|, |W|[|i|], |S|[|i|] and |C|[|i|] all have the same shape:
Which serialize back to the same original shorthand value,
because the longhands are repeater aligned:
all three properties have the same number of items (3),
and each item is a single value (not a repeater).
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
Which serialize back to the same original shorthand value,
because the longhands are repeater aligned:
all three properties have the same number of items (2),
and at each index the items have matching types
(single values at index 0, integer repeaters at index 1),
the integer repeaters have the same repeat count (2),
and the integer repeaters contain the same number of values (1).
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
Which serialize back to the same original shorthand value,
because the longhands are repeater aligned:
all three properties have the same number of items (1),
each item is an auto repeater,
and the auto repeaters contain the same number of values (2).
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
The 'column-rule' shorthand will serialize as an empty string
because the longhands are not repeater aligned:
the auto repeaters contain different numbers of values.
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
The 'column-rule' shorthand will serialize as an empty string
because the longhands are not repeater aligned:
the items at index 0 have mismatched types
(integer repeater for width and color, single value for style).
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
The 'column-rule' shorthand will serialize as an empty string
because the longhands are not repeater aligned:
the integer repeaters have different repeat counts.
The same behavior would occur if the three longhands were specified directly
rather than coming from a shorthand.
Many thanks to Sam Davis Omekara Jr. and Javier Contreras Tenorio
who contributed a significant amount of normative text, examples, and WPT coverage to this specification.
Mats Palmgren's earlier
proposal
for Gap Decorations helped inform the direction of this specification.
Additional feedback that helped shape this specification was contributed by many people, including:
Ahmad Shadeed,
Alison Maher,
Benoît Rouleau,
Elika Etemad,
Ian Kilpatrick,
Josh Tumath,
Kurt Catti-Schmidt,
Lea Verou,
Oliver Williams,
Rachel Andrew,
Sebastian Zartner,
Tab Atkins-Bittner,
and the CSS Working Group members.
Privacy Considerations
No new privacy considerations have been reported on this specification.
Security Considerations
No new security considerations have been reported on this specification.