刚接触 CSS 布局时,最常纠结的问题之一就是:这个布局该用 Flexbox 还是 Grid? 网上众说纷纭,有的说"能用 Flex 就不用 Grid",有的说"Grid 是未来"。 其实两者并不是竞争关系,而是解决不同维度问题的工具。理解它们的定位,选型自然就清楚了。
核心区别:一维 vs 二维
官方文档对两者的定位非常明确:
- Flexbox 是一维布局模型——一次只处理一个维度(行 或 列)上的排列与对齐;
- Grid 是二维布局模型——同时处理行与列,可以先把"骨架"画出来,再把内容放进去。
这个区别决定了它们各自擅长的场景。导航栏、按钮组、卡片内的图文排布,本质都是"一行(或一列)上的分布", 用 Flexbox 最顺手;而整个页面的骨架、宫格相册、Dashboard 面板这类"先有行列结构,再填内容"的布局, 用 Grid 最直观。
Flexbox 的典型场景
Flexbox 的核心能力是 沿主轴分布 + 沿交叉轴对齐,配合
justify-content、align-items、flex-grow 等属性,
能轻松实现很多以前要靠 float + margin 才能凑出来的效果:
.navbar {
display: flex;
justify-content: space-between; /* 两端对齐,中间自动留白 */
align-items: center; /* 垂直居中 */
}
.btn-group {
display: flex;
gap: 12px; /* 间距由 gap 负责,不用再写 margin */
}
.card-body {
display: flex;
flex-direction: column;
/* 卡片底部按钮"吸底"的经典写法: */
margin-top: auto;
}
gap 属性是近几年最舒服的改进之一——以前用 Flexbox 做间距要靠
margin + 各种 :not(:last-child) 选择器,
现在一行 gap 全部搞定,Flex 和 Grid 都支持。
Grid 的典型场景
Grid 的思维方式是"先画网格,再放元素"。定义列宽、行高、区域,内容自动落入对应位置:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 16px;
}
.page-shell {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 220px 1fr;
grid-template-rows: auto 1fr auto;
}
.page-shell header { grid-area: header; }
.page-shell aside { grid-area: sidebar; }
.page-shell main { grid-area: main; }
.page-shell footer { grid-area: footer; }
注意 repeat(auto-fill, minmax(240px, 1fr)) 这种写法:
它让卡片墙在窄屏自动降为单列、宽屏自动铺满,完全不需要写媒体查询,
是"响应式宫格"最省力的方案。
选型建议
我自己的判断标准很简单,按顺序问三个问题:
- 内容只在一个方向上排列(一行按钮、一列表单)→ 用 Flexbox;
- 需要行和列同时控制(页面骨架、宫格)→ 用 Grid;
- 不确定?先看元素之间的"对齐"关系更重,还是"区域划分"更重——前者 Flex,后者 Grid。
另外,二者完全可以嵌套混用:外层 Grid 搭骨架,内部某个区域再用 Flex 排细节,这是最常见的组合。
常见误区
- "Flexbox 不能做二维"——用 flex-wrap 可以换行,但换行后的对齐控制远不如 Grid 精确,属于"能做但别扭";
- "Grid 一定比 Flex 好"——Grid 的书写模型更复杂,简单的行内分布用它属于杀鸡用牛刀;
- 忘了旧浏览器——如果项目还需要支持 IE11,Grid 的很多新语法(如 gap、auto-fill)会失效,需要额外兜底。
总结:Flexbox 管"一排",Grid 管"一盘"。先用语义判断维度,再动手写代码,选型就不会纠结。