← 🟩 CSS Grid · 二维布局与轨道模型 / display: contents:让包裹层消失,子项直上父网格 待审核 7 / 8
display: contents · 穿透

display: contents:让包裹层消失,子项直上父网格

Grid / Flex 只对直接子元素建立项。可现实里容器与真正的内容之间常隔着一层语义包裹——列表的 <li>、组件的根 <div>。这层会独占一个网格单元,把内部的多个元素「闷」在里面,无法各自对齐到父网格的列。display: contents 让一个元素自身不生成盒子,其子元素上移一层、直接成为父级的项。于是用一个扁平 grid 就能让多行结构对齐——这是 subgrid 普及前的常用替代,至今仍有其位置。

一句话: display: contents =「保留我的子元素在文档流里,但丢弃我自己的盒子(及其 border / background / padding)」。它不同于 display: none(连子元素一起移除)。

1 · 切换包裹层:block ↔ contents

下面有 3 行,每行被一个橙框 .row 包裹。父网格是 auto 1fr auto 三列。block 时每个 .row 占满整行的第一个单元、三段内容挤在框内不对齐;切到 contents,橙框消失、每行的「名称 / 进度条 / 数值」上浮成为父网格的项,跨行对齐到三列。

2 · 代价与注意

方面 说明
自身盒子消失 该元素的 border / background / padding / box-shadow 全部不再渲染(上面橙框消失即此)。要这些装饰就不能用它。
尺寸 / 定位失效 width / height / position / overflow / transform 对它无意义(它没有盒子)。
对 replaced 无效 <img> / <video> / <input> 等替换元素与表单控件上,contents 被当作普通 inline / 原显示,不会「消失」。
a11y 历史坑 早期浏览器会把它连同子元素一起从无障碍树移除(语义丢失)。主流引擎已修复,但语义元素(如 <ul> / <table> 结构)上仍需回归测试。
vs subgrid contents 是把中间层抹掉;subgrid保留中间层并让其继承父轨道。需要保留 .row 的边框 / 背景 / 事件时用 subgrid。

本页的「名称 / 进度条 / 数值」三列对齐,正是 实战页grid + display: contents 那一版的核心;实战页把它和 tablesubgrid 几种做法并排,逐一拆解取舍。