CSS Gap Decorations: row-rule and column-rule for Grid and Flex

Grid and flexbox dividers without borders or pseudo-elements

Putting lines between grid or flex items always meant putting borders on the items themselves, then stripping the border off the last column and last row with nth-child selectors. Gap decorations let the container draw the rules instead.

Old way 15 lines
.grid   {  display: grid;  grid-template-columns: repeat(3, 1fr);  gap: 24px;}.grid > *   {  border-inline-end: 1px solid #ddd;  border-block-end: 1px solid #ddd;}.grid > :nth-child(3n)   {  border-inline-end: 0;}.grid > :nth-last-child(-n + 3)   {  border-block-end: 0;}
Modern
5 lines
.grid   {  display: grid;  grid-template-columns: repeat(3, 1fr);  gap: 24px;  column-rule: 1px solid var(--border);   row-rule: 1px solid var(--border); }
Limited availability 40% global usage

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Not ready for production without a fallback.

149+
rule lines between grid items, drawn by the grid itself
A
B
C
D
E
F
column-rule + row-rule

Drawn by the container

Rules live on the grid or flex container, not on each child. No per-item borders to add, no nth-child selectors to strip the last column or row.

Reflows with the layout

Change the column count or wrap items differently and the rules adjust automatically. No selectors tied to a fixed column count.

Full border shorthand

Use the same width, style, and color syntax as border. Plus rule-break, rule-outset, and gap-rule-paint-order for fine control over intersections.

Lines Saved
15 → 5
No nth-child math
Old Approach
item borders
+ nth-child resets
Modern Approach
row-rule / column-rule
Container property

How it works

Dividers between grid or flexbox items were always painful. The usual trick was to put a border on every item, then write nth-child selectors to remove the border from the last column and last row. Change the column count and the selectors broke. Wrap items at a different breakpoint and the trailing borders showed up again.

The row-rule and column-rule properties move that responsibility to the container. The grid or flex parent draws the rules inside its gaps. They accept the same shorthand as border, so column-rule: 1px solid #ddd reads naturally. Add rule-outset to extend rules past the gap, rule-break to control behavior at intersections, and gap-rule-paint-order to decide which axis paints over the other.

ESC