CSS Grid 布局深度指南:从 Flexbox 思维到二维布局范式
Flexbox 和 Grid 的差异不是”一维 vs 二维”这么简单——它们是两种不同的布局思维模型。Flexbox 是”内容驱动”的(flex items 决定自己的尺寸),Grid 是”容器驱动”的(grid tracks 的尺寸由容器定义)。理解这个区别,才能知道什么时候该用哪个。
fr 单位的本质
1fr 是 Grid 中最强大的单位,但很多人把它理解为”百分比”。实际上,fr 是”剩余空间的一份”。关键区别:
/* 三列等宽,但 gap 的处理方式不同 */
.grid-fr {
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
/* 总宽度减去 40px gap 后,剩余空间三等分 */
}
.grid-percent {
grid-template-columns: calc(33.33% - 13.33px) calc(33.33% - 13.33px) calc(33.33% - 13.33px);
/* 手动计算 gap,脆弱且难维护 */
}
fr 会自动扣除 gap 后再分配,这是它比百分比优雅的根本原因。
auto-fill vs auto-fit:一个被低估的差异
这两者看起来相似,但在只有少量项目时行为完全不同:
/* auto-fill:即使没有足够内容,也会创建空轨道 */
.grid-fill {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* 假如容器宽 1000px,会创建 5 列,即使只有 3 个 item */
}
/* auto-fit:拉伸已有项目填充空间 */
.grid-fit {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* 同样 1000px 宽 3 个 item,每列拉伸到约 333px */
}
实际场景判断:卡片列表用 auto-fill(即使不满一行也保持卡片原始宽度),仪表盘面板用 auto-fit(让面板自动撑满)。
Subgrid:对齐嵌套网格
Grid 的一个常见痛点是:嵌套元素无法与父级网格对齐。Subgrid 解决了这个问题:
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid; /* 继承父级的列定义 */
/* 子元素的列现在与父级网格完全对齐 */
}
浏览器支持在 2024 年已基本完善(Chrome 117+、Firefox 71+、Safari 16+)。对于卡片内的复杂表单布局,subgrid 可以避免硬编码列宽。
Grid 与 Flexbox 的协作策略
不要在 Grid 和 Flexbox 之间二选一。它们解决的问题不同,可以嵌套使用:
- 页面整体布局(header/sidebar/main/footer)→ Grid
- 导航栏(水平排列的链接列表)→ Flexbox
- 卡片内部(标题、描述、按钮的垂直排列)→ Flexbox(
flex-direction: column) - 表单布局(标签和输入框的二维对齐)→ Grid
一个实用的判断标准:如果你需要同时控制行和列的对齐,用 Grid。如果你只需要控制一个方向的对齐,用 Flexbox。
常见的性能陷阱
Grid 布局本身不会造成性能问题,但某些使用方式会:
- 避免在
grid-template-columns中使用calc()嵌套多层计算 gap属性在大量子元素(1000+)时可能触发重排,此时考虑使用margin替代- 频繁改变
grid-template-areas会触发整个网格的重计算
Grid 的学习曲线在理解了 fr 和轨道概念后会迅速平缓。关键是从”用 Flexbox 的思维硬套 Grid”切换到”用 Grid 的思维重新看待布局问题”。二维布局用 Grid 实现的代码量,通常只有 Flexbox 嵌套方案的三分之一。