我有一支技术全面、经验丰富的小型团队,专注高效交付中等规模外包项目,有需要外包项目的可以联系我

2017 年,我给一家金融科技客户做了个 Logo 墙: 5x5 的网格,间距刚刚好,强迫症看了都能舒一口气。

正当我暗爽“这回真干净”, 客户来了一句:

“能不能在每个 Logo 之间加上分隔线?看起来更‘专业’一点。”

然后,我就掉进了三个小时的地狱。

  • 随着视口变化要改布局;

  • 我往 DOM 里塞了一堆只负责画边框的空 span

  • 辅助技术一来的时候,键盘导航直接被这些“假元素”干崩;

视觉上,在桌面端看着还行。 但一旦有人调整浏览器宽度、或者用 Tab 键跳焦点—— 整个体验立刻暴露出一个字:

“怪。”

时间快进到 2025 年底。

Edge 和 Chrome 139 悄悄加了一个新东西:

CSS Gap Decorations(间隙装饰)

换句话说:你终于可以直接给 grid / flex 的“gap 本身”加样式了。不用再到处加假元素。

我花了两周拿它疯狂做实验, 把当年的那个 Logo 墙重新写了一遍—— 用了 20 分钟,心态非常平静。

接下来,我们拆开看看: 这个 2025 最“勾人”的 CSS 新特性, 到底让我们少掉了多少眼泪。

你已经见过的语法,现在换了个地方发光

如果你以前用过多列布局里的 column-rule, 那 Gap Decorations 的语法,看一眼就明白。

它给了我们两大类属性:

  • 列方向的装饰(column-rule- 系列)

  • 行方向的装饰(row-rule- 系列)

每一侧都可以分别控制:

  • 线宽(width)

  • 线型(style)

  • 颜色(color)

精细到「横竖分开管」

/* 列方向装饰 */
column-rule-width: 2px;
column-rule-style: solid;
column-rule-color: #333;

/* 行方向装饰 */
row-rule-width: 1px;
row-rule-style: dashed;
row-rule-color: #999;

想图省事?一样有简写

/* 列的三个属性打包 */
column-rule: 2px solid #333;

/* 行的三个属性打包 */
row-rule: 1px dashed #999;

甚至还有一个「双向通吃」的终极简写

/* 行列一起上 */
rule: 1px solid black;

重点是:

这套语法不区分 grid / flex, 你不用记两份名字。

熟悉的写法 + 新的能力, 上手几乎没门槛。

rule-break:告诉“线条”遇到跨行跨列时别乱来

rule-break 系列控制的是:

当你的“分隔线”遇到跨行 / 跨列元素、 或者两条线交叉的时候,它们要怎么“让位”。

一共有三个值:

/* 列装饰 */
column-rule-break: none;          /* 线直接穿过去,谁挡都不停 */
column-rule-break: intersection;  /* 到交叉点就停 */
column-rule-break: spanning-item; /* 遇到跨行/跨列元素就停 */

/* 行装饰 */
row-rule-break: none;
row-rule-break: intersection;
row-rule-break: spanning-item;

/* 行列一起控制 */
rule-break: intersection;

这在什么场景特别管用?

比如:日历 / 排程布局

  • 顶部有跨多列的表头;

  • 下面是按列分的时间格子。

你只要:

rule-break: spanning-item;

纵向分隔线自然会停在表头下面, 不再需要写那些恐怖的 :nth-child() 条件。

rule-outset:决定线头在线与线交叉处“伸出去多少”

rule-outset 控制的是:

装饰线在交叉点处,要不要伸长一点、缩短一点、还是刚好碰头。

/* 控制装饰线从中心位置延伸多少 */
column-rule-outset: 50%; /* 默认:两条线在中间刚好碰上 */
column-rule-outset: 0px; /* 对齐到间隙两端边缘 */
column-rule-outset: 5px; /* 稍微伸出一点 */
column-rule-outset: -5px; /* 稍微缩回一点 */

/* 行同理 */
row-rule-outset: 50%;

/* 行列一起控制 */
rule-outset: 5px;

百分比值会跟着 gap 宽度变化,非常适合:

  • gap 在不同断点下会变大变小的响应式布局。

不用再钉死一个固定像素,然后在每个 breakpoint 里反复改。

rule-paint-order:当横竖线相遇,谁在上面?

rule-paint-order 决定的是绘制顺序:

行的“线”压在列上,还是列压在行上?

/* 行装饰覆盖在列装饰之上 */
rule-paint-order: row-over-column;

/* 列装饰盖在行装饰之上 */
rule-paint-order: column-over-row;

这个细节, 在“精致感”上非常要命。

比如你做一个横线是蓝色、左边一条红色竖线当“边界”的笔记本纸效果

.notebook {
  display: grid;
  gap: 24px 32px;
  row-rule: 1px solid #b3d9ff;
  column-rule: 2px solid #ff6b6b;
  rule-paint-order: column-over-row;
}

红色那条“边界线”自然会压在蓝色横线之上, 效果就跟纸质本子一模一样。

repeat():给间隙装饰也安排节奏感

跟 grid 里的 repeat() 类似, Gap Decorations 也支持模式重复

简单重复

/* 每条横向 gap 都画同样的线 */
row-rule: repeat(solid);

交替样式

/* 列方向:实线、点线交替 */
column-rule-style: repeat(solid dotted);

更复杂一点的节奏

/* 两条细黑线 + 一条粗红线循环 */
row-rule: repeat(2, 1px solid black) 3px solid red;

/* 多个属性都可以用 repeat */
column-rule-width: repeat(1px 2px);           /* 细粗交替 */
column-rule-color: repeat(#BADA55 #C0FFEE);   /* 颜色交替 */

auto 可以帮你把剩下的 gap 自动填满模式。

以前你要为了这种节奏感写一堆 nth-child 现在一句 repeat 就结束战斗。

回到那个 2017 年的 Logo 墙:重构只要 20 分钟

还记得开头那个噩梦 Logo grid 吗?

  • 当年为了加那几条分隔线,

  • 我给每个 Logo 加伪元素;

  • 用 nth-child 防止最右、最下那条线多画;

  • 用绝对定位撑线,

  • 还要小心 keyboard navigation 不要被挡。

现在,用 Gap Decorations,可以写成这样:

<ul>
 <li><img src="logo-a.svg" alt="a logo of brand A"></li>
 <li><img src="logo-b.svg" alt="a logo of brand B"></li>
 <li><img src="logo-c.svg" alt="a logo of brand C"></li>
 <li><img src="logo-d.svg" alt="a logo of brand D"></li>
 <li><img src="logo-e.svg" alt="a logo of brand E"></li>
</ul>
ul {
display: grid;
gap: 1rem;
justify-items: center;

row-rule-width: 1px;
row-rule-style: solid;
row-rule-color: black;

column-rule-width: 1px;
column-rule-style: solid;
column-rule-color: black;

  @media (width > 600px) {
    grid-template-columns: repeat(5, 1fr);
  }
}

因为行列都用同样的线宽/线型/颜色, 我们还能进一步偷懒,用终极简写:

ul {
  display: grid;
  gap: 1rem;
  justify-items: center;

  rule: 1px solid black;

  @media (width > 600px) {
    grid-template-columns: repeat(5, 1fr);
  }
}

没有任何额外 DOM。 没有伪元素。 没有 nth-child 黑魔法。 辅助技术也清清爽爽。

高阶玩法:当“间隙”开始帮你做设计,而不是添乱

下面是我这两周折腾出来的一些有趣用法。

颜色节奏感:让视觉分区更柔和

.feature-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;

/* 基础列分隔线 */
column-rule: 1px solid black;
column-rule-width: 1px2px; /* 1px / 2px 交替 */

/* 每三行,用点线做一个“节拍” */
row-rule: 1px solid black;
row-rule-style: solid solid dotted;
}

这种“有一点变化但不过分吵闹”的节奏, 非常适合:

  • 功能卡片列表;

  • 优势对比模块;

  • 需要微妙分组感的布局。

用不同 gap 装饰做“区域层级”

.dashboard {
display: grid;
grid-template: 
    "header header header" auto
    "sidebar main main"1fr
    "footer footer footer" auto / 1fr 1fr 1fr;
gap: 1.5rem;

/* 默认分隔线风格 */
row-rule: 1px solid #ddd;
column-rule: 1px solid #ddd;

/* header 和内容之间的分隔更醒目 */
row-rule-width: 3px1px;
row-rule-color: #0074d9#ddd;

/* 中间主内容区域取消竖线 */
column-rule-width: 1px0px1px;
}

不用额外加 wrapper,只通过 gap 的装饰:

  • 让 header 和正文之间的分割更“有仪式感”;

  • 让中间主内容区域显得更“宽”,更流畅。

装饰型填充:让网格间隙像 UI 设计稿里的那种“小花样”

.gallery-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
position: relative;

/* 给装饰线留一点“呼吸空间” */
row-rule-outset: 1rem;
column-rule-outset: 1rem;

/* 显示分隔线 */
row-rule: 1px dashed #0074d9;
column-rule: 1px dashed #0074d9;
}

/* 每个 item 里再加一点小装饰 */
.gallery-grid.gallery-item {
position: relative;
}

.gallery-grid.gallery-item::after {
content: "";
position: absolute;
width: 1.5rem;
height: 1.5rem;
background: 
    radial-gradient(circle at center, #0074d9 0.25rem, transparent 0.25rem),
    repeating-linear-gradient(45deg, #0074d9 0, #0074d9 2px, transparent 2px, transparent 8px);
border-radius: 50%;
bottom: -1.75rem;
right: -1.75rem;
z-index: 2;
}

/* 最后一列不画角落装饰 */
.gallery-grid.gallery-item:nth-child(3n)::after {
display: none;
}

/* 最后一行也不画 */
.gallery-grid.gallery-item:nth-last-child(-n+3)::after {
display: none;
}

这里的关键组合是:

  • 用 rule-outset 把线从交叉点“拉出来一点”;

  • 再用伪元素在交叉点附近画一些更复杂的小装饰;

整个网格会有一种“刻意设计过”的高级感, 而不是简单的表格。

跟主题联动的视觉:让间隙也懂“暗黑模式”

:root {
--gap-primary-color: #0074d9;
--gap-secondary-color: #ddd;
--gap-width-small: 1px;
--gap-width-large: 3px;
}

.dark-theme {
--gap-primary-color: #61dafb;
--gap-secondary-color: #444;
}

.content-sections {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;

/* 跟主题绑定的 gap 装饰 */
column-rule: var(--gap-width-small) solid var(--gap-secondary-color);
row-rule: var(--gap-width-large) dotted var(--gap-primary-color);

/* 可以根据主题调整“伸出去”的长度 */
row-rule-outset: calc(var(--gap-width-large) * 2);
}

你只要在主题切换的时候改几个 CSS 变量:

  • gap 的颜色、线宽、甚至位置, 就能自动“跟妆”, 完全不用动布局代码。

浏览器支持:是时候真的敢在项目里用了

截至 2025 年 11 月:

  • Edge

  • Chrome 139+

已经支持 Gap Decorations。

具体你现在手上的浏览器行不行,可以自己去 Can I Use 上查一眼。

对于内部工具、面向现代浏览器的项目来说, 已经完全够资格“上正式环境”了。

结语:终于可以在“gap 本身”画线,而不是继续到处打补丁

过去这么多年, 我们为了在 grid / flex 的间隙中画一条线, 干的事大概是这样的:

  • DOM 里塞假元素;

  • 用伪元素表示“不是内容的内容”;

  • 无数 nth-child 黑魔法处理边界情况;

  • 还要担心辅助技术认错焦点。

Gap Decorations 上来之后, 这句话终于可以划掉了:

“CSS 不支持直接在 gap 上画线。”

现在我们可以:

  • 在真正的间隙位置画东西;

  • 保持 DOM 干净、语义正确;

  • 让键盘导航和屏幕阅读器自然工作;

  • 同时还拥有节奏、层级、主题切换这些高级玩法。

如果你还没试过, 真的值得开一个小 demo 玩一玩。

说不定你也会像我一样, 改完一个老项目后, 默默在心里给这玩意儿点个赞:

“这可能是 2025 年最性感的 CSS 小特性。”

感谢你看到这里。 我们下次再聊一个新的 CSS 小惊喜。

全栈AI·探索:涵盖动效、React Hooks、Vue 技巧、LLM 应用、Python 脚本等专栏,案例驱动实战学习,点击二维码了解更多详情。

图片

最后:

Vue 设计模式实战指南 

20个前端开发者必备的响应式布局

深入React:从基础到最佳实践完整攻略

python 技巧精讲

React Hook 深入浅出

CSS技巧与案例详解

vue2与vue3技巧合集

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐