Flex 与 Grid 布局:什么时候用哪个

布局不用再靠 float 和 position 硬凑了。Flex 和 Grid 各有擅长,选对了代码能少一半。

一、怎么选

场景
一维排列(一行或一列)Flex
二维网格(行 + 列同时控制)Grid
导航栏、工具栏、卡片内元素对齐Flex
页面整体分区、卡片网格、表单Grid

判断方法:需要同时控制行和列吗? 需要就 Grid,否则 Flex。

二、Flex 核心

css
.container {
  display: flex;
  flex-direction: row;        /* 主轴方向:row | column */
  justify-content: space-between;  /* 主轴对齐 */
  align-items: center;            /* 交叉轴对齐 */
  gap: 12px;                      /* 间距,比 margin 好用 */
}

子项属性:

属性作用
flex: 1占据剩余空间
flex: none不伸缩,保持原尺寸
flex-shrink: 0不允许收缩(防止图标被压扁)
margin-left: auto推到最右(比 justify-content 灵活)

高频坑:内容溢出

Flex 子项默认 min-width: auto,长文本会撑破容器。解法:

css
.item {
  min-width: 0;      /* 允许收缩到比内容小 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

布局一:顶部导航栏

css
.header {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 64px;
}
.header nav { flex: 1; }        /* 中间撑开 */
.header .right { margin-left: auto; }

三、Grid 核心

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 三等分 */
  gap: 18px;
}

.item {
  grid-column: span 2;        /* 跨两列 */
  grid-row: span 2;
}

自适应卡片网格(最实用的一条)

css
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 18px;
}

一行代码搞定响应式:容器能放几个就放几个,每个至少 300px,剩余空间平分。不用写媒体查询。

auto-fillauto-fit 的区别:

行为
auto-fill空间够就多放空轨道(即使没内容)
auto-fit折叠空轨道,现有项拉伸填满

大多数情况两者效果一样,元素少时 auto-fit 会让它们拉伸变宽。

布局二:圣杯布局(内容 + 侧边栏)

css
.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 240px;
  gap: 40px;
  align-items: start;
}

@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; }
}

minmax(0, 1fr) 而不是 1fr:前者允许内容区收缩到 0,避免长代码块把侧边栏挤出屏幕。这是本站文章页用的写法。

布局三:底部固定在底部的页脚

css
body {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;   /* 头 / 内容 / 脚 */
}

四、居中:三种方式

css
/* 1. Flex,最通用 */
.parent { display: flex; justify-content: center; align-items: center; }

/* 2. Grid,最短 */
.parent { display: grid; place-items: center; }

/* 3. 绝对定位 */
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

五、gap 取代 margin

css
/* 旧写法:最后一个元素会有多余间距 */
.item { margin-right: 12px; }
.item:last-child { margin-right: 0; }

/* 新写法 */
.container { display: flex; gap: 12px; }

Flex 和 Grid 都支持 gap(以前叫 grid-gap),这是比 margin 干净得多的方案。

六、对齐属性速查

属性用于控制
justify-content容器主轴上各项目的分布
align-items容器交叉轴上项目如何对齐
align-content容器多行时行与行的分布
align-self子项单个项目的交叉轴对齐

记忆:Flex 里 justify 管主轴,align 管交叉轴。主轴方向由 flex-direction 决定,column 时两者会互换——这是最容易记混的地方。

七、本站用到的组合

css
/* 卡片网格 */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }

/* 文章页:主内容 + 目录 */
.post-layout { display: grid; grid-template-columns: minmax(0, 1fr) 216px; gap: 44px; align-items: start; }

/* 头部:品牌 + 导航 + 右侧工具 */
.header-inner { display: flex; align-items: center; gap: 16px; height: 64px; }

/* 上一篇/下一篇 */
.pager { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

八、调试技巧

Chrome DevTools 里选中元素,看 Flex/Grid 的叠加标记;还可以在样式面板里点 display: flex 旁边的小图标快速切换。

css
/* 临时给所有元素描边,看布局边界 */
* { outline: 1px solid red !important; }

布局的现代写法就这两套。掌握 flex 的三个属性和 gridrepeat(auto-fill, minmax()),90% 的场景都能解决。