一篇文章掌握 Flexbox 布局的所有常用操作
📚 目录
- 基础概念
- 容器属性
- 子元素属性
- 常见布局场景
- 实战技巧
- 最佳实践
基础概念
什么是 Flexbox?
Flexbox(弹性盒子布局)是 CSS3 引入的一种一维布局模型,用于在容器中分配空间和对齐项目。
核心概念
┌──────────────────────────────────────┐ ← flex container(容器) │ 主轴起点 主轴终点 │ │ ↓ ↓ │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ ← flex items(子项) │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │ ←────────── 主轴(main axis)────→ │ │ ↑ │ │ 交叉轴(cross axis) │ └──────────────────────────────────────┘关键术语:
- Flex Container(容器):设置了
display: flex的父元素 - Flex Items(子项):容器的直接子元素
- 主轴(Main Axis):默认水平方向,由
flex-direction决定 - 交叉轴(Cross Axis):垂直于主轴的方向
容器属性
1.display: flex
启用 Flexbox 布局
.container{display:flex;/* 块级 flex 容器 *//* 或 */display:inline-flex;/* 行内 flex 容器 */}2.flex-direction
定义主轴方向
.container{flex-direction:row;/* 默认,水平从左到右 */flex-direction:row-reverse;/* 水平从右到左 */flex-direction:column;/* 垂直从上到下 */flex-direction:column-reverse;/* 垂直从下到上 */}可视化:
row: [1] [2] [3] [4] → row-reverse: ← [4] [3] [2] [1] column: [1] [2] [3] [4] ↓ column-reverse: ↑ [4] [3] [2] [1]3.justify-content
主轴对齐方式(水平对齐,当 flex-direction 为 row 时)
.container{justify-content:flex-start;/* 默认,起点对齐 */justify-content:flex-end;/* 终点对齐 */justify-content:center;/* 居中对齐 */justify-content:space-between;/* 两端对齐,项目间距相等 */justify-content:space-around;/* 每个项目两侧间距相等 */justify-content:space-evenly;/* 所有间距完全相等 */}可视化:
flex-start: [1] [2] [3] | flex-end: [1] [2] [3] | center: [1] [2] [3] | space-between: [1] [2] [3] | space-around: [1] [2] [3] | space-evenly: [1] [2] [3] |4.align-items
交叉轴对齐方式(垂直对齐,当 flex-direction 为 row 时)
.container{align-items:stretch;/* 默认,拉伸填充 */align-items:flex-start;/* 起点对齐 */align-items:flex-end;/* 终点对齐 */align-items:center;/* 居中对齐 */align-items:baseline;/* 基线对齐 */}可视化:
stretch: ┌─────┐ ┌─────┐ ┌─────┐ │ 1 │ │ 2 │ │ 3 │ │ │ │ │ │ │ └─────┘ └─────┘ └─────┘ flex-start: ┌─────┐ ┌─────┐ ┌─────┐ │ 1 │ │ 2 │ │ 3 │ └─────┘ └─────┘ └─────┘ center: ┌─────┐ ┌─────┐ ┌─────┐ │ 1 │ │ 2 │ │ 3 │ └─────┘ └─────┘ └─────┘ flex-end: ┌─────┐ ┌─────┐ ┌─────┐ │ 1 │ │ 2 │ │ 3 │ └─────┘ └─────┘ └─────┘5.flex-wrap
是否换行
.container{flex-wrap:nowrap;/* 默认,不换行 */flex-wrap:wrap;/* 换行,第一行在上 */flex-wrap:wrap-reverse;/* 换行,第一行在下 */}可视化:
nowrap: [1] [2] [3] [4] [5] [6] →(可能溢出) wrap: [1] [2] [3] [4] [5] [6] wrap-reverse: [5] [6] [1] [2] [3] [4]6.align-content
多行对齐方式(仅在有多行时生效)
.container{flex-wrap:wrap;/* 必须先设置换行 */align-content:stretch;/* 默认,拉伸 */align-content:flex-start;/* 起点对齐 */align-content:flex-end;/* 终点对齐 */align-content:center;/* 居中 */align-content:space-between;/* 两端对齐 */align-content:space-around;/* 间距相等 */}7.gap(现代属性)
设置子项间距
.container{display:flex;gap:20px;/* 所有方向 *//* 或 */row-gap:20px;/* 行间距 */column-gap:10px;/* 列间距 */}子元素属性
1.flex-grow
放大比例(如何分配剩余空间)
.item{flex-grow:0;/* 默认,不放大 */flex-grow:1;/* 平分剩余空间 */flex-grow:2;/* 获得 2 倍空间 */}示例:
.item1{flex-grow:1;}/* 占 1 份 */.item2{flex-grow:2;}/* 占 2 份 */.item3{flex-grow:1;}/* 占 1 份 */┌──────────────────────────────────────┐ │ [item1] │ [item2──────] │ [item3] │ │ 25% │ 50% │ 25% │ └──────────────────────────────────────┘2.flex-shrink
缩小比例(空间不足时如何收缩)
.item{flex-shrink:1;/* 默认,会收缩 */flex-shrink:0;/* 不收缩 */flex-shrink:2;/* 2 倍收缩速度 */}3.flex-basis
项目的基础大小
.item{flex-basis:auto;/* 默认,根据内容 */flex-basis:200px;/* 固定宽度 */flex-basis:30%;/* 百分比 */}4.flex(简写属性)⭐
最常用的简写
.item{/* flex: flex-grow flex-shrink flex-basis */flex:0 1 auto;/* 默认值 */flex:1;/* flex: 1 1 0% */flex:auto;/* flex: 1 1 auto */flex:none;/* flex: 0 0 auto */}常用值:
/* 自动填充剩余空间 */.item{flex:1;}/* 固定宽度,不收缩不放大 */.item{flex:0 0 200px;}/* 根据内容,可放大可缩小 */.item{flex:auto;}5.align-self
单个项目的对齐方式(覆盖 align-items)
.item{align-self:auto;/* 默认,继承 align-items */align-self:flex-start;align-self:flex-end;align-self:center;align-self:baseline;align-self:stretch;}6.order
改变项目排列顺序
.item{order:0;/* 默认 */order:-1;/* 提前 */order:1;/* 延后 */}示例:
.item1{order:2;}.item2{order:1;}.item3{order:3;}HTML: [1] [2] [3] 显示: [2] [1] [3]常见布局场景
1. 水平垂直居中 ⭐⭐⭐
.container{display:flex;justify-content:center;/* 水平居中 */align-items:center;/* 垂直居中 */height:100vh;/* 容器高度 */}<divclass="container"><divclass="centered-item">完美居中</div></div>2. 两端对齐布局
.header{display:flex;align-items:center;justify-content:space-between;}<divclass="header"><divclass="logo">Logo</div><navclass="menu">Menu</nav></div>┌───────────────────────────────────┐ │ [Logo] [Menu] │ └───────────────────────────────────┘3. 左侧固定,右侧自适应
.layout{display:flex;}.sidebar{flex:0 0 250px;/* 固定宽度 250px */}.content{flex:1;/* 占满剩余空间 */}<divclass="layout"><asideclass="sidebar">侧边栏</aside><mainclass="content">主内容</main></div>┌─────────┬──────────────────────────┐ │ Sidebar │ Content (自适应) │ │ 250px │ │ └─────────┴──────────────────────────┘4. 等分布局
.grid{display:flex;gap:20px;}.grid-item{flex:1;/* 每个子项等宽 */}<divclass="grid"><divclass="grid-item">1</div><divclass="grid-item">2</div><divclass="grid-item">3</div></div>┌──────────┬──────────┬──────────┐ │ 1 │ 2 │ 3 │ └──────────┴──────────┴──────────┘5. 圣杯布局(Holy Grail)
.container{display:flex;flex-direction:column;min-height:100vh;}.header, .footer{flex:0 0 auto;}.main{flex:1;display:flex;}.sidebar{flex:0 0 200px;}.content{flex:1;}<divclass="container"><headerclass="header">Header</header><divclass="main"><asideclass="sidebar">Sidebar</aside><mainclass="content">Content</main></div><footerclass="footer">Footer</footer></div>┌──────────────────────────┐ │ Header │ ├────────┬─────────────────┤ │ Side │ Content │ │ bar │ (自适应高度) │ ├────────┴─────────────────┤ │ Footer │ └──────────────────────────┘6. 卡片网格布局
.card-grid{display:flex;flex-wrap:wrap;gap:20px;}.card{flex:0 0calc(33.333% - 14px);/* 3 列 */}/* 响应式 */@media(max-width:768px){.card{flex:0 0calc(50% - 10px);/* 2 列 */}}@media(max-width:480px){.card{flex:0 0 100%;/* 1 列 */}}7. 底部固定布局
.container{display:flex;flex-direction:column;min-height:100vh;}.content{flex:1;/* 内容区自动填充 */}.footer{flex:0 0 auto;}┌──────────────────────────┐ │ Content │ │ │ │ (自动扩展) │ │ │ ├──────────────────────────┤ │ Footer │ ← 始终在底部 └──────────────────────────┘8. 导航栏布局
.navbar{display:flex;align-items:center;padding:0 20px;}.logo{margin-right:auto;/* Logo 左侧,其他右侧 */}.nav-links{display:flex;gap:20px;}<navclass="navbar"><divclass="logo">Logo</div><ulclass="nav-links"><li>Home</li><li>About</li><li>Contact</li></ul><buttonclass="login">Login</button></nav>┌─────────────────────────────────────────┐ │ [Logo] [Home][About][Contact][Login] │ └─────────────────────────────────────────┘实战技巧
1. Auto Margin 技巧 ⭐⭐⭐
在 Flexbox 中,margin: auto可以消耗所有剩余空间
推送到右侧
.container{display:flex;}.item-left{/* 正常布局 */}.item-right{margin-left:auto;/* 推到最右边 */}<divclass="container"><divclass="item-left">Left</div><divclass="item-right">Right</div></div>┌─────────────────────────────────────┐ │ [Left] [Right] │ └─────────────────────────────────────┘水平垂直居中(单个元素)
.container{display:flex;}.centered{margin:auto;/* 完美居中 */}2. 最后一行左对齐
问题:使用justify-content: space-between时,最后一行会两端对齐
/* 方法 1:添加空白占位符 */.grid::after{content:'';flex:auto;}/* 方法 2:使用 gap 代替 justify-content */.grid{display:flex;flex-wrap:wrap;gap:20px;}.item{flex:0 0calc(33.333% - 14px);}3. 溢出滚动
.container{display:flex;overflow-x:auto;/* 水平滚动 */}.item{flex:0 0 200px;/* 固定宽度,不收缩 */}4. 反转布局
/* HTML 顺序:A B C *//* 显示顺序:C B A */.container{display:flex;flex-direction:row-reverse;}/* 或使用 order */.item-a{order:3;}.item-b{order:2;}.item-c{order:1;}5. 垂直居中多行文本
.container{display:flex;align-items:center;min-height:200px;}.text{/* 多行文本也会垂直居中 */}6. 按钮组布局
.button-group{display:flex;gap:10px;}/* 左对齐 */.button-group.left{justify-content:flex-start;}/* 右对齐 */.button-group.right{justify-content:flex-end;}/* 居中 */.button-group.center{justify-content:center;}7. 固定比例布局
/* 比例 2:3:1 */.item1{flex:2;}.item2{flex:3;}.item3{flex:1;}┌────┬─────────┬───┐ │ 2 │ 3 │ 1 │ └────┴─────────┴───┘8. 响应式导航
.nav{display:flex;gap:20px;}@media(max-width:768px){.nav{flex-direction:column;/* 垂直排列 */}}最佳实践
1. ✅ 优先使用flex简写
/* ❌ 不推荐 */.item{flex-grow:1;flex-shrink:1;flex-basis:0%;}/* ✅ 推荐 */.item{flex:1;}2. ✅ 使用gap代替margin
/* ❌ 老方法 */.container{display:flex;}.item{margin-right:20px;}.item:last-child{margin-right:0;}/* ✅ 新方法 */.container{display:flex;gap:20px;}3. ✅ 避免不必要的嵌套
/* ❌ 过度嵌套 */.outer{display:flex;}.middle{display:flex;flex:1;}.inner{display:flex;}/* ✅ 扁平化 */.container{display:flex;}4. ✅ 使用min-width: 0解决文本溢出
/* 问题:flex item 中长文本不换行 */.item{flex:1;min-width:0;/* 允许收缩到 0 */}.text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}5. ✅ 考虑浏览器兼容性
/* 添加前缀(现代构建工具会自动处理) */.container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}6. ✅ 合理使用align-itemsvsalign-content
/* 单行对齐用 align-items */.container{display:flex;align-items:center;}/* 多行对齐用 align-content */.container{display:flex;flex-wrap:wrap;align-content:center;}7. ✅ 防止内容撑大容器
.container{display:flex;}.item{flex:1;min-width:0;/* 允许收缩 */overflow:hidden;/* 裁剪溢出 */}快速参考表
容器属性速查
| 属性 | 作用 | 常用值 |
|---|---|---|
display | 启用 Flexbox | flex,inline-flex |
flex-direction | 主轴方向 | row,column |
justify-content | 主轴对齐 | center,space-between |
align-items | 交叉轴对齐 | center,stretch |
flex-wrap | 是否换行 | wrap,nowrap |
gap | 间距 | 20px,1rem |
子元素属性速查
| 属性 | 作用 | 常用值 |
|---|---|---|
flex | 缩放比例 | 1,0 0 200px |
align-self | 单独对齐 | center,flex-start |
order | 排列顺序 | 0,-1,1 |
常用组合速查
| 场景 | CSS |
|---|---|
| 水平垂直居中 | display: flex; justify-content: center; align-items: center; |
| 两端对齐 | display: flex; justify-content: space-between; |
| 等分布局 | display: flex; .item { flex: 1; } |
| 固定+自适应 | .fixed { flex: 0 0 200px; } .auto { flex: 1; } |
| 底部固定 | display: flex; flex-direction: column; .content { flex: 1; } |
在线工具推荐
Flexbox Playground
- https://codepen.io/enxaneta/pen/adLPwv
- 交互式学习 Flexbox
Flexbox Froggy
- https://flexboxfroggy.com/
- 游戏化学习
CSS Tricks Guide
- https://css-tricks.com/snippets/css/a-guide-to-flexbox/
- 完整参考文档
Flexbox Defense
- http://www.flexboxdefense.com/
- 塔防游戏学习
总结
记住这 3 个核心概念:
display: flex- 启用 Flexbox- 主轴对齐-
justify-content(水平) - 交叉轴对齐-
align-items(垂直)
记住这 2 个常用技巧:
flex: 1- 自动填充空间margin: auto- 推送元素到边缘
记住这 1 个黄金法则:
先理解主轴和交叉轴,90% 的布局问题都能解决!
实战练习
试着用 Flexbox 实现以下布局:
- ✅ 登录页面(垂直水平居中的表单)
- ✅ 导航栏(Logo 左侧,菜单右侧)
- ✅ 卡片列表(3 列响应式网格)
- ✅ 个人中心页(左侧导航,右侧内容)
- ✅ 移动端底部标签栏
参考资源
- MDN Flexbox 文档
- W3C Flexbox 规范
- Can I Use - Flexbox