Flex 与 Grid — CodeRoadMapFlex 与 Grid
这一课你将能做到
- 用 Flex 写出水平垂直居中、自适应导航、卡片列表
- 用 Grid 写出多列网格、圣杯布局
- 知道什么场景用 Flex、什么场景用 Grid
为什么要学
Flex 和 Grid 是现代 CSS 布局的两大支柱。在它们出现之前,居中一个 div 都是难题,要写各种 hack。现在两横一纵三行代码搞定。Flex 擅长一维(一行或一列),Grid 擅长二维(行和列同时控)。
人话:Flex 像把东西摆在一条传送带上——只管一个方向的排列;Grid 像 Excel 表格——行和列同时布局。
先建立图像
<style>
.flex {
display: flex;
justify-content: space-between; /* 主轴均分 */
align-items: center; /* 交叉轴居中 */
background: #f0f0f0;
padding: 10px;
}
.flex > div { background: tomato; color: #fff; padding: 10px 20px; }
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 列等分 */
gap: 10px;
margin-top: 20px;
}
.grid > div { background: skyblue; padding: 20px; }
</style>
<div class="flex">
<div>A</div><div>B</div><div>C</div>
</div>
<div class="grid">
<div>1</div><div>2</div><div>3</div>
<div>4</div><div>5</div><div>6</div>
</div>
跟着做
步骤 1:Flex 容器属性
.container {
display: flex;
flex-direction: row; /* 主轴方向:row / row-reverse / column / column-reverse */
flex-wrap: nowrap; /* 换行:nowrap / wrap / wrap-reverse */
justify-content: flex-start; /* 主轴对齐:flex-start / center / flex-end / space-between / space-around / space-evenly */
align-items: stretch; /* 交叉轴对齐:stretch / flex-start / center / flex-end / baseline */
gap: 16px; /* 项目间距 */
}
最常用组合:
/* 水平垂直居中 */
.center {
display: flex;
justify-content: center;
align-items: center;
}
/* 两端对齐 */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
}
步骤 2:Flex 项目属性
.item {
flex-grow: 0; /* 多余空间是否放大:默认 0 */
flex-shrink: 1; /* 空间不足是否缩小:默认 1 */
flex-basis: auto; /* 基准大小 */
/* 简写:flex: grow shrink basis */
flex: 1; /* 等价于 1 1 0%,常用!均分剩余空间 */
flex: 0 0 200px; /* 固定 200px,不放大不缩小 */
align-self: center; /* 单个项目覆盖 align-items */
order: 2; /* 排序,越小越靠前 */
}
实战:左侧固定 200px、右侧自适应的两栏:
.page { display: flex; }
.side { flex: 0 0 200px; background: #eee; }
.main { flex: 1; }
步骤 3:Flex 实战——卡片列表
<style>
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 250px; /* 最小 250px,能放大 */
background: #fff;
border: 1px solid #eee;
padding: 16px;
border-radius: 8px;
}
</style>
<div class="cards">
<div class="card">卡片 1</div>
<div class="card">卡片 2</div>
<div class="card">卡片 3</div>
<div class="card">卡片 4</div>
</div>
步骤 4:Grid 容器基础
.grid {
display: grid;
grid-template-columns: 200px 1fr 1fr; /* 三列:200px + 两个等分 */
grid-template-rows: 100px auto; /* 两行:100px + 自适应 */
gap: 16px 24px; /* 行距 列距 */
}
/* 常用写法 */
.grid {
grid-template-columns: repeat(3, 1fr); /* 3 等分 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* 自适应列数 */
}
fr 单位:fraction,剩余空间的比例分配。1fr 2fr 表示 1:2 比例。
步骤 5:Grid 项目放置
.item-a {
grid-column: 1 / 3; /* 占据第 1 列线到第 3 列线(跨 2 列) */
grid-row: 1 / 2;
}
.item-b {
grid-column: 3 / 4;
grid-row: 1 / 3; /* 跨 2 行 */
}
步骤 6:Grid 实战——圣杯布局
<style>
.layout {
display: grid;
grid-template-areas:
"header header header"
"side main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 60px 1fr 60px;
min-height: 100vh;
}
.header { grid-area: header; background: #ffd93d; }
.side { grid-area: side; background: #ffb6b9; }
.main { grid-area: main; background: #c7ecee; }
.aside { grid-area: aside; background: #dff9fb; }
.footer { grid-area: footer; background: #95afc0; }
</style>
<div class="layout">
<header class="header">Header</header>
<nav class="side">Side</nav>
<main class="main">Main</main>
<aside class="aside">Aside</aside>
<footer class="footer">Footer</footer>
</div>
grid-template-areas 让布局像画图一样直观。
步骤 7:Flex vs Grid 怎么选
- 一维布局用 Flex:导航栏、按钮组、标签列表
- 二维布局用 Grid:卡片网格、整页布局、图片画廊
- Flex 是「内容驱动」:项目大小由内容决定
- Grid 是「布局驱动」:先定义网格,再把内容放进去
讲清楚要点
- Flex 主轴和交叉轴:
flex-direction: row 时主轴是横向;column 时主轴是纵向。justify-content 永远管主轴,align-items 永远管交叉轴。
- flex: 1 是
1 1 0% 的简写:均分剩余空间。
- Grid 的 1fr 是剩余空间:和 Flex 的
flex: 1 类似,但 Grid 是先减去固定列再按比例分。
- gap 属性现在 flex 和 grid 都支持:替代了之前用 margin hack 的历史。
auto-fill vs auto-fit:auto-fill 留空轨道,auto-fit 把空轨道塌掉。
你可能会懵的地方
-
Flex 项目设了宽度为什么没生效?
检查 flex-shrink,默认是 1,空间不足会被压缩。改 flex-shrink: 0。
-
Grid 子元素怎么居中?
用 place-items: center(容器),或 place-self: center(项目)。
-
flex: 1 和 width: 33% 区别?
flex: 1 是「分剩余空间」,受兄弟影响;width: 33% 是「我固定 33%」,不影响兄弟。
-
为什么 gap 在老浏览器不行?
flex 的 gap 是 2021 年才全浏览器支持的。要兼容老浏览器用 margin。
-
Grid 项目能重叠吗?
能,让它们占据同一条 track 即可,配合 z-index 控制层叠。
错法对照
| 错法 | 问题 | 正解 |
|---|
display: flex 后子元素 width 失效 | flex-shrink 默认压缩 | flex-shrink: 0 |
| 用 float 做整体布局 | 已过时 | flex/grid |
justify-content: center 想垂直居中 | 它只控主轴 | 加 align-items: center |
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 重复 5 次 | 冗余 | repeat(5, 1fr) |
| 强行用 grid 做导航条 | 杀鸡用牛刀 | 简单一维用 flex |
卡点急救
- flex 子元素被压缩看不见:加
flex-shrink: 0 或 min-width。
- grid 列数算错:F12 → Layout 面板 → 勾选 Grid 复选框,可视化网格线。
- 水平垂直居中总是不居:父元素加
display: flex; justify-content: center; align-items: center; 一行解决。
面试常问
-
Flex 和 Grid 的区别?
Flex 是一维布局,处理行或列;Grid 是二维布局,同时处理行和列。Flex 是内容驱动,Grid 是布局驱动。
-
flex: 1 等于什么?
flex: 1 1 0%,即可放大、可缩小、基准 0。常用于等分剩余空间。
-
怎么实现水平垂直居中?
Flex 法:display: flex; justify-content: center; align-items: center;
Grid 法:display: grid; place-items: center;
绝对定位法:position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
自测三问
flex-direction: column 时,justify-content 控制什么方向?
grid-template-columns: 200px 1fr 2fr 在 1000px 容器里,三列各多宽?
- 响应式卡片列表该用 Flex 还是 Grid?为什么?
小结一句话
Flex 管一条线,Grid 管一个面;日常 80% 用 Flex,复杂二维用 Grid;掌握 justify-content + align-items + repeat(auto-fill, minmax()) 三个武器就够用。
延伸