刚接触 CSS 布局时,最常纠结的问题之一就是:这个布局该用 Flexbox 还是 Grid? 网上众说纷纭,有的说"能用 Flex 就不用 Grid",有的说"Grid 是未来"。 其实两者并不是竞争关系,而是解决不同维度问题的工具。理解它们的定位,选型自然就清楚了。

核心区别:一维 vs 二维

官方文档对两者的定位非常明确:

  • Flexbox 是一维布局模型——一次只处理一个维度(行 列)上的排列与对齐;
  • Grid 是二维布局模型——同时处理行与列,可以先把"骨架"画出来,再把内容放进去。

这个区别决定了它们各自擅长的场景。导航栏、按钮组、卡片内的图文排布,本质都是"一行(或一列)上的分布", 用 Flexbox 最顺手;而整个页面的骨架、宫格相册、Dashboard 面板这类"先有行列结构,再填内容"的布局, 用 Grid 最直观。

Flexbox 的典型场景

Flexbox 的核心能力是 沿主轴分布 + 沿交叉轴对齐,配合 justify-contentalign-itemsflex-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)) 这种写法: 它让卡片墙在窄屏自动降为单列、宽屏自动铺满,完全不需要写媒体查询, 是"响应式宫格"最省力的方案。

选型建议

我自己的判断标准很简单,按顺序问三个问题:

  1. 内容只在一个方向上排列(一行按钮、一列表单)→ 用 Flexbox
  2. 需要行和列同时控制(页面骨架、宫格)→ 用 Grid
  3. 不确定?先看元素之间的"对齐"关系更重,还是"区域划分"更重——前者 Flex,后者 Grid。

另外,二者完全可以嵌套混用:外层 Grid 搭骨架,内部某个区域再用 Flex 排细节,这是最常见的组合。

常见误区

  • "Flexbox 不能做二维"——用 flex-wrap 可以换行,但换行后的对齐控制远不如 Grid 精确,属于"能做但别扭";
  • "Grid 一定比 Flex 好"——Grid 的书写模型更复杂,简单的行内分布用它属于杀鸡用牛刀;
  • 忘了旧浏览器——如果项目还需要支持 IE11,Grid 的很多新语法(如 gap、auto-fill)会失效,需要额外兜底。

总结:Flexbox 管"一排",Grid 管"一盘"。先用语义判断维度,再动手写代码,选型就不会纠结。