CSS 现代布局完全指南:Flexbox 和 Grid 从入门到实战
别再用 float 和 margin hack 了。2026 年了,是时候彻底掌握现代 CSS 布局了。
我见过太多前端开发者(包括曾经的我)写 CSS 布局的方式是:先 display: flex,然后开始疯狂加 margin、padding、position: absolute,直到「看起来对了」为止。这种写法的问题是——换个屏幕尺寸就全崩了。
这篇文章不是属性查询手册(那种东西 MDN 更好),我想做的是:用真实的布局场景,把 Flexbox 和 Grid 的核心思维模型讲清楚。掌握了思维模型,你遇到任何布局需求都能快速选择正确的方案。
1. 核心区别:一维 vs 二维
这是理解 Flexbox 和 Grid 最重要的一句话:
Flexbox = 一维布局系统 ↓ 在一个方向上排列元素(一行或一列) ↓ 适合:导航栏、按钮组、卡片行、工具栏 Grid = 二维布局系统 ↓ 同时控制行和列 ↓ 适合:页面整体布局、仪表盘、表单、图片画廊
选择原则
内容优先 → Flexbox:你不知道会有多少个子元素,让内容决定布局(比如标签列表、评论区)。
布局优先 → Grid:你知道页面的布局结构(几行几列),让布局容纳内容(比如管理后台、landing page)。
实际项目中,两者经常混用:Grid 做页面大框架,Flexbox 处理每个区域内部的排列。
2. Flexbox 进阶:超越 justify-content
flex-grow / flex-shrink / flex-basis
大多数人只用 flex: 1,但不知道它是三个属性的简写。理解这三个属性,你就能精确控制元素如何分配空间。
flex: <flex-grow> <flex-shrink> <flex-basis>
flex-basis → 元素在分配剩余空间之前的「基准尺寸」
flex-grow → 有多余空间时,按什么比例分配
flex-shrink → 空间不够时,按什么比例收缩
// flex: 1 等于 flex: 1 1 0%
// 意思是:基准尺寸 0,等比例伸展和收缩
// 实用写法
.sidebar { flex: 0 0 280px } // 固定 280px,不伸展不收缩
.content { flex: 1 1 0% } // 占满剩余空间
.aside { flex: 0 0 200px } // 固定 200px
实战:经典导航栏
/* Logo 在左,菜单在中间,按钮在右 */
.navbar {
display: flex;
align-items: center;
gap: 1rem;
}
.logo { flex: 0 0 auto; } /* 固有尺寸 */
.nav-links { flex: 1; text-align: center; } /* 占满中间 */
.actions { flex: 0 0 auto; } /* 固有尺寸 */
/* 为什么不用 margin-left: auto?
用 flex-grow 更语义化,而且在 RTL 语言下自动适配 */
实战:flex-wrap 做响应式卡片
/* 不用媒体查询就能实现响应式卡片布局! */
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
flex: 1 1 300px; /* 最小 300px,多余空间等比例分配 */
/* 大屏:一行 3-4 张卡片 */
/* 小屏:自动换行,可能一行 1-2 张 */
}
/* 关键技巧:用 max-width 防止单独一行时卡片拉太宽 */
.card {
flex: 1 1 300px;
max-width: 400px;
}
3. CSS Grid 进阶:从 fr 到 grid-template-areas
fr 单位:灵活的比例分配
/* fr = fraction(比例份额)*/
.grid {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
/* 总共 4 份,左右各 1 份,中间 2 份 */
/* 比百分比好的地方:fr 会自动减去 gap */
gap: 1rem;
}
/* 混合使用固定值和 fr */
.layout {
grid-template-columns: 280px 1fr;
/* 左侧固定 280px 的侧边栏,右侧自适应 */
}
/* 经典 12 列栅格 */
.grid-12 {
grid-template-columns: repeat(12, 1fr);
}
.col-span-4 { grid-column: span 4; }
.col-span-8 { grid-column: span 8; }
grid-template-areas:可视化布局
这是 CSS Grid 最酷的特性——你可以用「ASCII art」的方式定义布局!
/* 经典后台管理布局 */
.dashboard {
display: grid;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
grid-template-columns: 240px 1fr 200px;
grid-template-rows: 60px 1fr 40px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* 响应式:小屏隐藏侧边栏 */
@media (max-width: 768px) {
.dashboard {
grid-template-areas:
"header"
"content"
"footer";
grid-template-columns: 1fr;
}
.sidebar, .aside { display: none; }
}
为什么 grid-template-areas 好用?
1. 可读性极强:一看就知道布局结构,不需要在脑子里算行列号。
2. 调整布局只需改一个地方:想把 sidebar 移到右边?改一下 areas 字符串就行,子元素的 CSS 完全不用动。
3. 天然防错:每一行必须有相同数量的区域名,否则 CSS 会忽略整个声明——这比错误地设置行列号好得多。
4. 终极响应式:auto-fill + minmax
如果你只记一个 Grid 技巧,记这个——不用写任何媒体查询就能实现完美响应式卡片布局:
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
/* 这一行代码做了什么:
- auto-fill:自动填充尽可能多的列
- minmax(280px, 1fr):每列最小 280px,最大等比例分配
- 大屏:4-5 列 | 中屏:2-3 列 | 小屏:1 列
- 完全自适应,不需要任何媒体查询! */
auto-fill vs auto-fit
auto-fill:即使没有足够的元素,也保留空的列轨道。
auto-fit:把空的列轨道折叠为 0,让现有元素拉伸填满整行。
大多数情况用 auto-fill 就对了。只有当你希望少量元素撑满整行时,才用 auto-fit。
5. Subgrid:终结「对不齐」的痛
卡片列表中最常见的问题:每张卡片的标题长度不同,导致描述文字的起始位置参差不齐。subgrid 就是用来解决这个问题的。
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
grid-template-rows: subgrid; /* 继承父级的行轨道 */
grid-row: span 3; /* 每张卡片占 3 行 */
/* 第 1 行:标题
第 2 行:描述
第 3 行:按钮
所有卡片的这三个区域会自动对齐! */
}
/* 之前的 hack 做法:
.title { min-height: 60px } ← 写死高度,不优雅
.description { flex: 1 } ← Flex 能拉伸但不能跨卡片对齐
subgrid 是真正的解决方案 */
subgrid 已经被所有现代浏览器支持(Chrome 117+, Firefox 71+, Safari 16+),2026 年可以放心使用。
6. 实战速查:常见布局一行搞定
/* 1. 水平垂直居中 */
.center {
display: grid;
place-items: center;
}
/* 2. 粘性页脚(footer 始终在底部) */
body {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
/* header = auto, main = 1fr(填满中间), footer = auto */
/* 3. 等高列 */
.equal-height {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
}
/* 4. Masonry 瀑布流(实验性) */
.masonry {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: masonry; /* Chrome 未支持,Firefox 已支持 */
}
/* 5. 两列表单(label + input 对齐) */
.form {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.75rem 1.5rem;
}
/* 6. 圣杯布局(header + 三栏 + footer)最简写法 */
.holy-grail {
display: grid;
grid-template:
"h h h" auto
"l m r" 1fr
"f f f" auto
/ 200px 1fr 200px;
min-height: 100vh;
}
/* grid-template 是以下三个属性的简写:
grid-template-areas
grid-template-rows
grid-template-columns
一行搞定,无需三个属性分开写 */
选择指南
场景 推荐方案 ────────────────────────────────────── 导航栏、按钮组、标签栏 Flexbox 卡片列表(数量不定) Flexbox (wrap) 或 Grid (auto-fill) 页面整体框架 Grid (template-areas) 仪表盘 / 管理后台 Grid 表单布局 Grid (两列) 居中一个元素 Grid (place-items: center) 一行内的水平排列 Flexbox
CSS 布局不再是「碰运气」。Flexbox 管好一维排列,Grid 管好二维结构,两者配合使用,几乎没有实现不了的布局。如果你还在纠结样式框架的选择,推荐看看 Tailwind CSS 使用体验分享。