Flex 弹性布局
Flex 是 CSS 中最常用的一维布局方案。它擅长处理横向一排或纵向一列的排列、对齐、间距和自适应问题。只要页面中的元素主要沿着一条轴线分布,Flex 通常就是非常自然的选择。
Flex 适合场景
Flex 适合处理一维方向上的布局,也就是主要关心“横着排”或者“竖着排”的场景。
常见场景:
- 导航栏左右分布
- 按钮组横向排列
- 图标和文字垂直居中
- 卡片内部上下分布
- 表单 label 和输入框对齐
- 列表项内部内容两端对齐
- 弹窗底部按钮靠右排列
- 头像、标题、描述组成的媒体对象
基础结构
下面代码表示父元素启用 Flex,子元素会自动成为 flex item,并沿主轴排列。
1.toolbar {2display: flex;3align-items: center;4gap: 16px;5}
这段代码可以理解为:
display: flex让父元素变成 flex container- 直接子元素会成为 flex item
align-items: center控制交叉轴居中gap: 16px控制子元素之间的间距
主轴和交叉轴
Flex 里最重要的概念是主轴和交叉轴。
默认情况下:
| 概念 | 默认方向 | 常用控制属性 |
|---|---|---|
| 主轴 | 从左到右 | justify-content |
| 交叉轴 | 从上到下 | align-items |
如果设置 flex-direction: column,主轴会变成从上到下,交叉轴会变成从左到右。
1.row {2display: flex;3flex-direction: row;4}56.column {7display: flex;8flex-direction: column;9}
常用属性
Flex 常用属性可以分成两类:一类写在父元素上,用来控制整体排列;另一类写在子元素上,用来控制单个项目如何伸缩。
display
启用 Flex 布局的入口是 display: flex。设置以后,父元素会成为 flex container,直接子元素会成为 flex item。
1.nav {2display: flex;3}
如果想让元素自身保持行内特性,也可以使用 inline-flex。
1.tag {2display: inline-flex;3align-items: center;4gap: 6px;5}
justify-content
justify-content 用来控制子元素在主轴上的分布方式。
1.nav {2display: flex;3justify-content: space-between;4}56.buttonGroup {7display: flex;8justify-content: center;9}
常见取值:
| 值 | 效果 |
|---|---|
flex-start | 靠主轴起点 |
center | 主轴居中 |
flex-end | 靠主轴终点 |
space-between | 两端贴边,中间平均分 |
space-around | 每个元素两侧都有间距 |
space-evenly | 所有间距完全相等 |
align-items
align-items 用来控制子元素在交叉轴上的对齐方式。最常见的用途是让图标和文字垂直居中。
1.menuItem {2display: flex;3align-items: center;4gap: 8px;5}
常见取值:
| 值 | 效果 |
|---|---|
stretch | 默认值,拉伸填满交叉轴 |
flex-start | 靠交叉轴起点 |
center | 交叉轴居中 |
flex-end | 靠交叉轴终点 |
baseline | 按文字基线对齐 |
gap
gap 用来控制 flex item 之间的间距。相比给每个子元素写 margin-right,gap 更干净,也不会出现最后一个元素多出间距的问题。
1.buttonGroup {2display: flex;3gap: 12px;4}
也可以分别设置行间距和列间距:
1.tagList {2display: flex;3flex-wrap: wrap;4row-gap: 10px;5column-gap: 12px;6}
flex-direction
flex-direction 用来改变主轴方向。
1.row {2display: flex;3flex-direction: row;4}56.card {7display: flex;8flex-direction: column;9}
常见取值:
| 值 | 说明 |
|---|---|
row | 从左到右排列 |
row-reverse | 从右到左排列 |
column | 从上到下排列 |
column-reverse | 从下到上排列 |
flex-wrap
默认情况下,Flex 子元素会尽量挤在一行里。如果内容太多,可以使用 flex-wrap: wrap 让它自动换行。
1.tagList {2display: flex;3flex-wrap: wrap;4gap: 10px;5}
这个属性常用于标签列表、按钮组、筛选条件等内容数量不固定的区域。
align-content
align-content 只在多行 Flex时生效,用来控制多行内容在交叉轴上的整体分布。
1.panel {2display: flex;3flex-wrap: wrap;4align-content: flex-start;5gap: 16px;6}
需要注意:如果只有一行,align-content 基本看不到效果,这时应该看 align-items。
子元素上的属性
父元素负责整体排列,子元素负责自己怎么伸缩。下面这些属性一般写在 flex item 上。
flex-grow
flex-grow 表示当容器有剩余空间时,子元素是否参与放大。
1.layout {2display: flex;3gap: 20px;4}56.main {7flex-grow: 1;8}910.aside {11width: 260px;12}
这里 .main 会吃掉剩余空间,.aside 保持固定宽度。
flex-shrink
flex-shrink 表示当空间不足时,子元素是否允许缩小。默认值是 1,也就是允许缩小。
1.avatar {2flex-shrink: 0;3width: 48px;4height: 48px;5}
头像、图标、固定按钮这类元素通常不希望被压扁,可以设置 flex-shrink: 0。
flex-basis
flex-basis 表示子元素在主轴上的初始尺寸。它比 width 更贴近 Flex 的语义。
1.item {2flex-basis: 240px;3}
flex 简写
flex 是 flex-grow、flex-shrink、flex-basis 的简写。
1.main {2flex: 1;3}45.sidebar {6flex: 0 0 260px;7}
可以简单理解:
| 写法 | 含义 |
|---|---|
flex: 1 | 可以放大、可以缩小、自动分配空间 |
flex: 0 0 260px | 不放大、不缩小,固定 260px |
flex: none | 基本不参与弹性伸缩 |
典型布局示例
导航栏左右分布
导航栏通常需要左侧放 logo,右侧放菜单或操作按钮。这个场景非常适合 Flex。
1.nav {2display: flex;3align-items: center;4justify-content: space-between;5height: 64px;6}78.navLinks {9display: flex;10align-items: center;11gap: 24px;12}
图标和文字对齐
图标和文字不对齐是很常见的问题。使用 Flex 后,只需要让它们在交叉轴居中。
1.infoItem {2display: inline-flex;3align-items: center;4gap: 8px;5}67.infoItem svg {8width: 18px;9height: 18px;10}
卡片内部上下分布
卡片内部经常需要标题在上方,标签或按钮固定贴近底部。可以让卡片使用纵向 Flex,再用 margin-top: auto 把底部内容推下去。
1.card {2display: flex;3flex-direction: column;4min-height: 220px;5padding: 20px;6}78.cardFooter {9margin-top: auto;10}
左侧固定,右侧自适应
后台页面、详情页、内容布局经常会用到左侧固定宽度,右侧自适应。
1.page {2display: flex;3gap: 24px;4}56.aside {7flex: 0 0 260px;8}910.content {11flex: 1;12min-width: 0;13}
这里 .content 加 min-width: 0 很重要,它可以避免右侧内容过长时把布局撑破。
弹窗底部按钮靠右
弹窗底部经常有“取消”和“确认”按钮,通常希望它们靠右排列。
1.modalFooter {2display: flex;3justify-content: flex-end;4gap: 12px;5}
等宽按钮组
如果希望一组按钮平均分配宽度,可以让每个按钮都使用 flex: 1。
1.actionGroup {2display: flex;3gap: 12px;4}56.actionGroup button {7flex: 1;8}
响应式 Flex 布局
Flex 很适合做轻量响应式。比如桌面端左右分布,移动端上下排列。
1.profile {2display: flex;3align-items: center;4gap: 24px;5}67@media (max-width: 640px) {8.profile {9flex-direction: column;10align-items: flex-start;11}12}
如果子元素数量不固定,可以配合 flex-wrap。
1.articleTools {2display: flex;3flex-wrap: wrap;4gap: 10px;5}
常见问题
子元素内容过长导致布局被撑开
在 Flex 布局中,如果某个子元素内部文本很长,可能会把容器撑开。常见解决方式是给 flex item 设置 min-width: 0。
1.listItem {2display: flex;3gap: 12px;4}56.listContent {7min-width: 0;8}910.title {11overflow: hidden;12white-space: nowrap;13text-overflow: ellipsis;14}
flex: 1 为什么有时不等宽
flex: 1 会参与剩余空间分配,但如果元素本身内容宽度差异很大,看起来可能仍然不完全等宽。想让它们更稳定,可以配合 min-width: 0。
1.tabs {2display: flex;3}45.tab {6flex: 1;7min-width: 0;8text-align: center;9}
margin 和 gap 怎么选
如果只是控制同级元素之间的间距,优先使用 gap。如果是某个元素需要特殊偏移,再考虑 margin。
1.list {2display: flex;3gap: 16px;4}56.submitButton {7margin-left: auto;8}
margin-left: auto 在 Flex 中很有用,它可以把某个元素推到另一侧。
align-items 没有生效
有时候看起来 align-items: center 没有生效,是因为元素高度不一致、内部文本换行,或者你真正想控制的是主轴方向。这时要先判断当前主轴是什么。
1.row {2display: flex;3align-items: center;4}56.column {7display: flex;8flex-direction: column;9justify-content: center;10}
Flex 和 Grid 怎么选
可以简单这样判断:
| 场景 | 推荐 |
|---|---|
| 一行或一列排列 | Flex |
| 同时控制行和列 | Grid |
| 图标文字对齐 | Flex |
| 按钮组、导航栏 | Flex |
| 卡片宫格、图片墙 | Grid |
| 后台复杂区域划分 | Grid |
使用建议
- 一维排列优先考虑 Flex
- 图标和文字对齐优先使用 Flex
- 子元素间距优先使用
gap - 内容可能过长时,记得给 flex item 设置
min-width: 0 - 固定宽度区域可以使用
flex: 0 0 宽度 - 自适应区域可以使用
flex: 1 - 同时控制行和列时,更适合使用 Grid
小结
Flex 的核心是沿着一条轴线分配空间。当布局问题主要发生在横向或纵向的一维方向上时,Flex 往往是最自然、最轻量的选择。掌握主轴、交叉轴、伸缩规则和常见布局模式后,大多数日常页面结构都可以用 Flex 写得很清晰。
