复习 CSS Flex 和 Grid 布局

还记得那些年被 CSS 布局折磨的日子吗?float: left 配合 clear: both,各种奇技淫巧只为让元素乖乖待在该待的地方。好在现代 CSS 给了我们两个布局神器:FlexGrid

如果你已经在用这两个布局方式,但偶尔还是会被轴向搞混,那这篇复习笔记正好适合你。我们会从最基础的概念开始,到实际的使用技巧,再到 Tailwind 的原子类封装,最后总结一些实战心得。

准备好了吗?复习开始!

Flex

Flex 被翻译为弹性布局,看名字就知道,主打一个 。(此处应有音效~ Duang~

一个弹性盒子里的内容我们只需要设置部分的宽度,其他没有设置的就能自如调整自己宽度,填满盒子。

最常见的需求写成代码如下:

html 复制代码
<div class="fixed-flex">
	<div class="side">侧边栏</div>
	<div class="main">主内容</div>
</div>

<style>
	.fixed-flex {
		display: flex;
	}
	.side {
		width: 200px;
		background: #ffecb3;
	}
	.main {
		flex-grow: 1;
		flex-shrink: 1;
		flex-basis: 0%;
		background: #fff9c4;
	}
</style>

.side 宽度固定 200px,对于 .main

  • 宽度不设置:flex-basis: 0%
  • 有多余空间时会膨胀:flex-grow: 1
  • 空间不足时收缩:flex-shrink: 1

以上 3 个值可以简写成一个 flex: 1,不过新手不推荐用除了 flex: 1 之外的 flex 属性,因为这个属性的语法有一点复杂

换行

有时候你确实不想只填满一行,Flex 也给你换行的选项。

html 复制代码
<div class="wrap-layout">
	<div>Akira</div>
	<div>Astro Boy</div>
	<div>Cowboy Bebop</div>
	<div>Dragon Ball Z</div>
	<div>Fullmetal Alchemist</div>
	<div>Ghost in the Shell</div>
	<div>Mobile Suit Gundam</div>
	<div>Neon Genesis Evangelion</div>
	<div>Princess Mononoke</div>
	<div>Sailor Moon</div>
</div>
<style>
	.wrap-layout {
		display: flex;
		flex-wrap: wrap;
		gap: 10px;
	}
	.wrap-layout div {
		width: auto;
		background: #c8e6c9;
		padding: 10px;
		text-align: center;
	}
</style>

默认情况下,Flex 布局只有单行,元素位置不够会被自动挤压,添加 flex-wrap: wrap; 后,就能保持其宽度自动换行。

交叉轴

Flexbox 的设计理念是一维布局,它要么是行(row),要么是列(column)。这意味着所有子元素都会沿着主轴(main axis) 排成一条线。但是换行之后就不可避免地成为二维布局,产生了交叉轴(cross axis) 的概念。

默认情况下,横着的是主轴,换行就产生了垂直于主轴的交叉轴。

与主轴有关的 CSS 属性带有 justify 前缀:

  • justify-content

与交叉轴有关的 CSS 属性带有 align 前缀:

  • align-content
  • align-items
  • align-self

align-content 控制的是多行的情况下 ,行与行之间的排布,你不用 wrap 的话这个属性是不会生效的;align-items 控制的是单行内元素的排布。

排列方向

我们可以通过 flex-direction: column; 切换主轴方向。

html 复制代码
<div class="column-layout">
	<div>上</div>
	<div>中</div>
	<div>下</div>
</div>

<style>
	.column-layout {
		display: flex;
		flex-direction: column;
		gap: 10px;
	}
</style>

十分简单!我们只需要一句 flex-direction: column; 就能把主轴从水平改为垂直,麻烦的它会给你带来一些思维负担。

上述所说的主轴、交叉轴、justify、align、换行概念都不变,只需要你把主轴换成垂直重新理解就好了,这不难,只是需要时间适应。

居中

Flex 拥有新时代最方便的居中布局的方法,justify-content: center;align-items: center;

2015 年就在干前端的老家伙们仍记得,当年还需要记各种 CSS 居中 hack,现在浏览器跟上了,大部分时间都只需要使用 Flex 就能解决问题。

正如上面所说,justify-content 是主轴元素间的分布,align-items 是交叉轴一维元素的分布,结合起来就是在 Flex 盒子内完全居中。

html 复制代码
<div class="center">
	<p>居中内容</p>
</div>
<style>
	.center {
		display: flex;
		justify-content: center;
		align-items: center;
		height: 200px;
		background: #f0f0f0;
	}
</style>

这时候有朋友就要提问了,用 align-content 从行的视角居中不可以吗?也是可以的,不过正如上面所说,必须设置 wrapalign-content 才能生效,所以得多加一行:

css 复制代码
.center {
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	align-content: center;
	height: 200px;
	background: #f0f0f0;
}

你可以在这个互动学习网站玩玩 Flex 的 wrapalignjustify 具体属性对元素布局的影响。

Bonus :Flex 父元素被撑爆了怎么办?当你设置了文字不换行之后,Flex 父元素经常会出现被撑爆的情况,这时候记得设置 overflow 属性。我觉得这里挺奇怪的,如果布局是垂直的时候,我会很容易想到设置 overflow,但是使用 Flex 之后布局变成水平了,我就老忘记设置 😂

Grid

Grid 布局就是一个画格子的游戏,一个例子让我们看看格子怎么画:

css 复制代码
.container {
	display: grid;
	grid-template-columns: 100px 200px auto;
	grid-template-rows: 50px auto 50px;
}

某种程度上 Grid 比 Flex 简单,因为基本不用切换主轴和交叉轴的概念,不容易记混。对于 Grid 我们只要知道行列怎么设置就行了。

grid-template-columns 设置 Grid 的列,100px 200px auto 的含义就是第一列 100px,第二列 200px,第三列自适应。

grid-template-rows 设置 Grid 的行,50px auto 50px 的含义就是第一行 50px,第二行自适应,第三行 50px。

还有一个十分实用的单位 fr,代表弹性比例(剩余空间的分数单位),举个例子:

css 复制代码
.container {
	display: grid;
	grid-template-columns: repeat(3, 1fr); /* 1fr 1fr 1fr */
}

这样就是把列分成均等的 3 份。

对齐

Flexbox 的子元素总是在主轴上紧密地排列在一起,没有多余空间可以用来让单个子元素进行单独的对齐,所以 Flex 不存在 justify-items。整个主轴上的对齐是由父容器的 justify-content 属性来统一控制的。它决定了所有子元素作为一个整体如何沿着主轴进行分布和对齐。

与之对比,Grid 就是画格子,格子画完之后,子元素在里面各自精彩,自然可以用 justify-items

命名网格

html 复制代码
<div class="grid-container">
	<header class="header">头部</header>
	<nav class="nav">导航</nav>
	<main class="content1">内容1</main>
	<main class="content2">内容2</main>
	<footer class="footer">底部</footer>
</div>
<style>
	.grid-container {
		display: grid;
		grid-template-areas:
			"header header header"
			"nav content1 content1"
			"nav content2 content2"
			"footer footer footer";

		grid-template-columns: 150px 1fr 1fr;
		grid-template-rows: 100px 1fr 1fr 60px;

		gap: 10px;
		height: 90vh;
	}
	.header {
		grid-area: header;
		background-color: #f0c3a2;
	}
	.nav {
		grid-area: nav;
		background-color: #a2d2ff;
	}
	.content1 {
		grid-area: content1;
		background-color: #b7efc5;
	}
	.content2 {
		grid-area: content2;
		background-color: #b7efc5;
	}
	.footer {
		grid-area: footer;
		background-color: #f2e293;
	}
</style>

不得不说这玩意有点好玩,在配置好行列宽高后,通过文字"画"出页面结构:

css 复制代码
"header header header"
"nav content1 content1"
"nav content2 content2"
"footer footer footer"

网格跨越

除了通过 grid-template-areas "画图",你还可以通过网格跨越设计页面元素。

css 复制代码
.grid-container {
	display: grid;
	grid-template-columns: 150px 1fr 1fr;
	grid-template-rows: 100px 1fr 1fr 60px;
	gap: 10px;
	height: 90vh;
}

.header {
	grid-column: 1 / 4;
	grid-row: 1 / 2;
	background-color: #f0c3a2;
}
.nav {
	grid-column: 1 / 2;
	grid-row: 2 / 4;
	background-color: #a2d2ff;
}
.content1 {
	grid-column: 2 / 4;
	grid-row: 2 / 3;
	background-color: #b7efc5;
}
.content2 {
	grid-column: 2 / 4;
	grid-row: 3 / 4;
	background-color: #b7efc5;
}
.footer {
	grid-column: 1 / 4;
	grid-row: 4 / 5;
	background-color: #f2e293;
}

grid-column 后面的数字表示从第 N 个竖线到第 M 个竖线中间的内容,这或许有点抽象,为什么要用竖线而不是第 N 列 这样的说法?

其实使用第 N 列的写法也有,例如:

css 复制代码
.header {
	grid-column: 1 / span 3;
	grid-row: 1 / span 1;
	background-color: #f0c3a2;
}

如果你要控制某个区间跨度,还是必须要以数字开始,再加 span 数字1 / span 3 代表从第 1 条竖线开始,跨度 3 列。

直接写 grid-column: span 3; 只能代表 3 列,不能控制开始位置。

对齐

Grid 也有 align-justify- 系列的对齐系统,它们的效果也与 Flex 里提到的类似。你可以在这个互动学习网站玩玩 Grid 的 alignjustify 具体属性对元素布局的影响。

place-content 是 CSS 中的一个简写属性,它同时设置了 align-contentjustify-content 这两个属性。它主要用于 Grid 布局,毕竟 Flex 布局比较少将这两个属性同时设置。举个例子

css 复制代码
place-content: center;
place-content: end space-between;

只填一个值的话同时应用到水平垂直,填两个值的话顺序是 place-content: <align-content> <justify-content>;

content 那有没有 items 呢?有的,朋友,如你所猜,就是 place-items,使用方法也是同理可得,就不多赘述了。

Grid 的浏览器支持比 Flex 差一点,不过仍然看好未来,现在用户更新浏览器应该是越来越容易了,保留旧浏览器的情况会比以前大大减少。

Tailwind

Tailwind 把常用的 Flex 与 Grid API 封装为原子类,直接在 class 中组合即可。某种程度上来说,直接从 Tailwind 学习 Flex 布局还好学一点,不过如果你是 Tailwind 的反对者,大可以跳过这一节。

下面用类名重现上文的关键示例:

Flex 基础

  • 容器与方向:
txt 复制代码
flex
flex flex-col
flex-row-reverse
flex-col-reverse
  • 间距与换行:
txt 复制代码
gap-4
gap-x-6 gap-y-2
flex-wrap
flex-nowrap

Flex 对齐

  • 主轴/交叉轴(容器):
txt 复制代码
flex justify-between items-center
flex justify-center items-stretch
  • 多行内容分布(容器,需要 flex-wrap 生效时才有体感):
txt 复制代码
flex flex-wrap content-between
flex flex-wrap content-center
  • 单个子项对齐(子项):
txt 复制代码
self-start
self-center
self-end
self-stretch

Flex 子项尺寸与顺序(子项)

  • 占比/伸缩/基础宽高:
txt 复制代码
flex-1
grow
shrink-0
basis-40

Grid 基础

  • 容器与网格轨道:
txt 复制代码
grid
grid-cols-3
grid-rows-4
  • 使用自定义列/行尺寸(对应上文 150px / 1fr / 1fr 与 100px / 1fr / 1fr / 60px):
txt 复制代码
grid grid-cols-[150px_1fr_1fr] grid-rows-[100px_1fr_1fr_60px] gap-2 h-[90vh]

用跨越重现上文布局

Tailwind 原生未提供 grid-template-areas 的原子类,上文示例可用 col-start/col-end 与 row-start/row-end 组合实现:

  • Header(跨 3 列,1 行):
txt 复制代码
col-start-1 col-end-4 row-start-1 row-end-2
  • Nav(第 1 列,从第 2 行跨到第 4 行):
txt 复制代码
col-start-1 col-end-2 row-start-2 row-end-4
  • Content1(第 2-3 列,第 2 行):
txt 复制代码
col-start-2 col-end-4 row-start-2 row-end-3
  • Content2(第 2-3 列,第 3 行):
txt 复制代码
col-start-2 col-end-4 row-start-3 row-end-4
  • Footer(跨 3 列,1 行):
txt 复制代码
col-start-1 col-end-4 row-start-4 row-end-5

同样可以用简写:

txt 复制代码
col-span-3 row-span-1

(在确定起始线的情况下用 start/end;仅控制跨度时可用 col-span-/row-span-。)

Grid 对齐

  • 同时设置 align-content 与 justify-content(容器):
txt 复制代码
place-content-center
place-content-between
  • 同时设置 align-items 与 justify-items(容器):
txt 复制代码
place-items-center
  • 仅水平/仅垂直(容器):
txt 复制代码
justify-items-start
align-items-end
  • 自动放置方向与紧密填充:
txt 复制代码
grid-flow-col
grid-flow-row-dense

Takeaways

  • Flex 更适合一维 分布与对齐,Grid 更适合二维网格与跨行跨列;实际项目里常用"外层 Grid 划区,内层 Flex 排内容"的混搭策略。
  • 牢记轴心:justify-* 作用在主轴,align-* 作用在交叉轴;切换为 column 后,两者随主轴一并"旋转"。
  • 换行的影响:只有设置了 flex-wrap 时,align-content 才会生效;单行关注 align-items/align-self,多行再谈 align-content
  • Flex 子项尺寸心法:固定 + 自适应 = 固定宽度 + flex: 1(等价 grow-1 shrink-1 basis-0%);除 flex: 1 外,新手谨慎使用更复杂的 flex 简写。
  • Grid 的核心是"画格子":grid-template-columns/rows 配合 fr 单位定义轨道;跨区用 grid-column/grid-row(如 1 / 4 或 1 / span 3);也可用 template-areas 直观命名布局。
  • 对齐总览:Grid 还支持 justify-items/align-items,以及 place-content/place-items 的简写组合,既能控制"内容整体",也能控制"单元格内"。
  • 兼容性与实践:Grid 支持略逊于 Flex,但现代浏览器基本可用;旧环境保守选 Flex,新项目优先考虑 Grid + Flex 混搭。

推荐阅读

相关推荐
_请输入用户名4 小时前
EventEmitter 是广播,Tapable 是流水线:聊聊它们的本质区别
前端·设计模式
爱学习的茄子4 小时前
React Fiber:让大型应用告别卡顿的性能革命
前端·react.js·面试
龙在天4 小时前
我是前端,我来总结一下前端 配 Nginx 的一些案例
前端
Thetimezipsby4 小时前
基于Taro4打造的一款最新版微信小程序、H5的多端开发简单模板
前端·javascript·微信小程序·typescript·html5·taro
掘金安东尼4 小时前
前端周刊430期(2025年9月1日–9月7日)
前端
BUG创建者4 小时前
uni 拍照上传拍视频上传以及相册
前端·javascript·音视频
就是帅我不改4 小时前
敏感词过滤黑科技!SpringBoot+Vue3+TS强强联手,打造无懈可击的内容安全防线
前端·vue.js·后端
JackJiang4 小时前
转转客服IM系统的WebSocket集群架构设计和部署方案
前端
codeGoogle4 小时前
大厂研发之谜:千亿投入砸出利润大缩水
前端·人工智能·后端