Flex 与 Grid 布局:什么时候用哪个
布局不用再靠 float 和 position 硬凑了。Flex 和 Grid 各有擅长,选对了代码能少一半。
一、怎么选
| 场景 | 用 |
|---|---|
| 一维排列(一行或一列) | Flex |
| 二维网格(行 + 列同时控制) | Grid |
| 导航栏、工具栏、卡片内元素对齐 | Flex |
| 页面整体分区、卡片网格、表单 | Grid |
判断方法:需要同时控制行和列吗? 需要就 Grid,否则 Flex。
二、Flex 核心
.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,长文本会撑破容器。解法:
.item {
min-width: 0; /* 允许收缩到比内容小 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}布局一:顶部导航栏
.header {
display: flex;
align-items: center;
gap: 16px;
height: 64px;
}
.header nav { flex: 1; } /* 中间撑开 */
.header .right { margin-left: auto; }三、Grid 核心
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 三等分 */
gap: 18px;
}
.item {
grid-column: span 2; /* 跨两列 */
grid-row: span 2;
}自适应卡片网格(最实用的一条)
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 18px;
}一行代码搞定响应式:容器能放几个就放几个,每个至少 300px,剩余空间平分。不用写媒体查询。
auto-fill 与 auto-fit 的区别:
| 值 | 行为 |
|---|---|
auto-fill | 空间够就多放空轨道(即使没内容) |
auto-fit | 折叠空轨道,现有项拉伸填满 |
大多数情况两者效果一样,元素少时 auto-fit 会让它们拉伸变宽。
布局二:圣杯布局(内容 + 侧边栏)
.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,避免长代码块把侧边栏挤出屏幕。这是本站文章页用的写法。
布局三:底部固定在底部的页脚
body {
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto; /* 头 / 内容 / 脚 */
}四、居中:三种方式
/* 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
/* 旧写法:最后一个元素会有多余间距 */
.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 时两者会互换——这是最容易记混的地方。
七、本站用到的组合
/* 卡片网格 */
.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 旁边的小图标快速切换。
/* 临时给所有元素描边,看布局边界 */
* { outline: 1px solid red !important; }布局的现代写法就这两套。掌握 flex 的三个属性和 grid 的 repeat(auto-fill, minmax()),90% 的场景都能解决。
