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.
.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;} .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; column-rule: 1px solid var(--border); row-rule: 1px solid var(--border); } gap decorations Browser Support
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.
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.
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.