引言
Flexbox 解决了一维布局的问题,但面对二维布局——既有行又有列——CSS Grid 才是真正的利器。然而很多开发者对 Grid 的使用停留在 grid-template-columns: 1fr 1fr 1fr 的水平。本文带你掌握 Grid 中那些能让代码更简洁、布局更灵活的高级技巧。
grid-template-areas:可视化的布局方式
grid-template-areas 是 Grid 最被低估的特性。它让你可以直接在 CSS 中以 ASCII 艺术的方式"画出"布局:
.page {
display: grid;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
在响应式设计中,只需修改 grid-template-areas 就能彻底改变布局:
@media (max-width: 768px) {
.page {
grid-template-areas:
"header"
"content"
"sidebar"
"aside"
"footer";
grid-template-columns: 1fr;
}
}
这种方式的优势在于:任何人看一眼 CSS 就能理解页面的整体布局结构,大幅降低维护成本。
auto-fill 与 auto-fit:不用写媒体查询的响应式网格
这是 Grid 中最"魔法"的特性。你不需要写任何 @media 查询,就能让网格自动适配屏幕宽度:
/* 每列最小 250px,空间不够自动换行 */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1.5rem;
}
auto-fill 和 auto-fit 的区别很微妙但很重要:
- auto-fill:尽可能多地创建轨道,即便没有内容填充,也会保留空轨道占位
- auto-fit:创建的轨道如果为空,会折叠它们,让已有内容拉伸填充
/* auto-fit: 内容较少时,卡片会自动拉伸填满整行 */
.grid-auto-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
经验法则:当你希望内容填满整行不留空白时用 auto-fit;当你希望保持列宽一致时用 auto-fill。
minmax():灵活的列宽控制
minmax() 函数让你同时定义轨道的最小和最大尺寸。它最常见的搭档就是 auto-fill/auto-fit,但它本身也非常强大:
/* 侧边栏最小 200px,最大 300px */
.layout {
display: grid;
grid-template-columns: minmax(200px, 300px) 1fr;
}
/* 内容区不超过 80ch 的可读宽度 */
.article-layout {
display: grid;
grid-template-columns: 1fr minmax(0, 80ch) 1fr;
}
.article-layout > * {
grid-column: 2;
}
place-items 与 place-content:对齐的快捷方式
Grid 中的对齐属性很多,但 place-items 和 place-content 是最实用的两个快捷属性:
/* 快速居中一个元素 */
.center-box {
display: grid;
place-items: center; /* align-items + justify-items */
}
/* 快速居中整个网格 */
.center-grid {
display: grid;
place-content: center; /* align-content + justify-content */
min-height: 100vh;
}
place-items: center 是目前最简洁的单元素居中方案,比 Flexbox 的 margin: auto 或绝对定位方案都要干净。
subgrid:嵌套网格的对齐利器
如果主网格中嵌套了子网格,子网格里的元素往往难以和主网格的轨道对齐。subgrid 解决了这个问题:
.card-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
grid-template-rows: subgrid; /* 继承父网格的行定义 */
grid-row: span 3; /* 占三行 */
}
/* 每张卡片的标题、内容、按钮自动对齐 */
使用 subgrid 后,所有 .card 内部的标题、正文和按钮会分别对齐到同一行,视觉效果非常整齐。目前 subgrid 已获得所有现代浏览器的支持。
Grid 与 Flexbox 的降级策略
尽管 Grid 的浏览器覆盖率已经超过 97%,但在处理老旧浏览器时可以这样降级:
/* 先写 Flexbox 作为降级方案 */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card-grid > * {
flex: 1 1 250px; /* 类似于 minmax 的效果 */
}
/* 再用 @supports 覆盖为 Grid */
@supports (display: grid) {
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.card-grid > * {
flex: unset; /* 清除 flex 相关属性 */
}
}
使用 @supports 查询可以让现代浏览器享受 Grid 的全部能力,同时保证老旧浏览器也有可用的布局。
实用技巧速查
- 固定头部+可滚动内容:
grid-template-rows: auto 1fr配合overflow: auto - 等宽多列:
grid-template-columns: repeat(3, 1fr) - 圣杯布局:
grid-template-columns: 200px 1fr 200px配合grid-template-areas - 瀑布流效果:
grid-auto-rows: masonry(实验性特性) - 重叠元素:使用
grid-column和grid-row让多个元素占据同一区域
总结
CSS Grid 远不止基本的行列定义。一旦你掌握了 grid-template-areas 带来的可视化布局、auto-fill/auto-fit 带来的零媒体查询响应式,以及 subgrid 带来的嵌套对齐,你就能用极少量的 CSS 实现过去需要大量 hack 才能完成的布局。我的建议是:新项目直接用 Grid,老项目在重构布局时逐步替换 Float 和过度的 Flexbox 嵌套。