← 返回文章列表
CSS·497 次阅读

Flexbox 还是 Grid?我的选型决策树

团队 Code Review 时又看到有人用 Flex 硬搓九宫格,一排三个换行靠 flex-wrap + 算宽度。我忍不住留了条评论:这个场景 Grid 三行代码就解决了。

这俩布局系统我都在生产环境深度用过,今天把选型经验整理成一篇。

一句话区分

  • Flexbox 是一维布局:处理"一行/一列怎么排"
  • Grid 是二维布局:处理"行和列同时怎么排"

这不是定义,是决策的第一原则。一维的问题用 Grid 能做但别扭,二维的问题用 Flex 能做但费劲。

先看 Flex 的主场

场景 1:导航栏、工具栏——典型的"一行东西排开":

.navbar {
  display: flex;
  align-items: center; /* 垂直居中 */
  gap: 16px;
}
.navbar .spacer {
  flex: 1; /* 把后面的项推到最右边 */
}

场景 2:内容驱动的分布——子项数量不固定、尺寸由内容决定:

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

标签云这种"有多少排多少、放不下就换行"的需求,Flex 的 flex-wrap 是天选。

场景 3:等高、居中、自适应伸缩:

.media {
  display: flex;
  gap: 12px;
}
.media .body {
  flex: 1; /* 吃掉剩余空间 */
  min-width: 0; /* 防止内容撑爆,老生常谈的坑 */
}

Flex 的关键词是内容驱动:子项多大、几个,布局跟着内容走。

再看 Grid 的主场

场景 1:页面骨架——头部、侧边栏、主区、底栏的经典布局:

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr auto;
  grid-template-areas:
    'header header'
    'sidebar main'
    'footer footer';
  min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

grid-template-areas 用 ASCII 图定义布局,一眼看懂结构,这是 Flex 永远给不了的可读性。

场景 2:整齐的卡片网格——开头说的九宫格:

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

/* 响应式版:自动填充,最小 280px */
.card-grid-auto {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

repeat(auto-fill, minmax()) 这行是 Grid 最香的模式:列数随容器宽度自动增减,不用写任何媒体查询。

场景 3:对齐要求严格的双轴布局——表单、仪表盘,行列都要对得整整齐齐的场景。

Grid 的关键词是布局驱动:先定好格子,内容往格子里填。

决策树

我自己脑内的判断流程是这样的:

要排的东西是"一行/一列"吗?
├─ 是 → 数量固定吗?
│  ├─ 固定,且要精确控制比例 → Flex
│  └─ 不固定,跟着内容走 → Flex(flex-wrap)
└─ 不是(行列都有)→ 行列结构是"布局先定"还是"内容先定"?
   ├─ 布局先定(页面骨架、仪表盘) → Grid
   ├─ 内容先定(卡片墙) → Grid 的 auto-fill
   └─ 只有一行但对齐复杂 → 多半还是 Flex + gap

简单粗暴版:一排用 Flex,一片用 Grid。

组合拳才是日常

真实项目里俩是嵌着用的。一个典型的卡片:

/* Grid 负责卡片的整体排布 */
.card-wall {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}

/* Flex 负责单张卡片内部的结构 */
.card {
  display: flex;
  flex-direction: column;
}
.card .content {
  flex: 1; /* 内容区吃掉剩余空间,让按钮贴底 */
}

外层 Grid 管"卡片们怎么摆",内层 Flex 管"卡片内部怎么排",flex: 1 还顺手解决了卡片高度不一致时按钮对不齐的老问题。

小结

  • Flex 一维、内容驱动;Grid 二维、布局驱动
  • 导航/工具栏/标签流 → Flex;页面骨架/卡片网格/仪表盘 → Grid
  • repeat(auto-fill, minmax(280px, 1fr)) 是响应式网格的银弹
  • 真实项目是组合拳:Grid 定大局,Flex 管局部

别再纠结"哪个更强"了,它们解决的是不同维度的问题。下次写布局前先问自己:这是一维还是二维?答案基本就出来了。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4