CSS Flexbox 弹性布局从零到精通 2026 | 零基础入门教程

你是否曾被网页布局搞得焦头烂额?用 float 排版总是错位,用 position 定位又总是对不齐?别担心,Flexbox(弹性布局)就是来拯救你的!这篇教程会从零开始,用大白话带你彻底搞懂 Flexbox。
一、什么是 Flexbox?
1.1 通俗理解
想象你有一个纸箱子(容器),里面放着几本书(子元素):
- 不用 Flexbox:书随便乱放,你很难控制它们的位置
- 用 Flexbox:你可以让书整齐排列、自动等间距、自动居中、自动撑满空间
一句话总结:Flexbox 就是让容器里的子元素「听话地排列」的一种布局方式。
1.2 什么时候用 Flexbox?
| 场景 | 例子 |
|---|---|
| 水平居中 | 一个按钮在导航栏中间 |
| 垂直居中 | 文字在卡片正中间 |
| 等间距排列 | 导航菜单的几个链接等距排开 |
| 自适应宽度 | 侧边栏固定宽度,内容区自动撑满 |
| 按钮组 | 几个按钮紧挨着排成一行 |
1.3 最简单的例子
先来个最简单的例子,感受一下 Flexbox 的魔力:
<!-- HTML -->
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>/* CSS */
.box {
display: flex; /* 加上这一行,魔法就发生了! */
}
.item {
width: 80px;
height: 80px;
background: #4a90d9;
color: white;
font-size: 24px;
text-align: center;
line-height: 80px; /* 让数字垂直居中 */
}发生了什么? 三个方块自动排成了一行,而且中间没有多余的空隙。这就是 Flexbox 最基本的效果。
💡 关键点:
display: flex写在父元素上,它会让所有直接子元素变成弹性布局。
二、两个核心概念:主轴和交叉轴
这是学习 Flexbox 最重要的概念,搞懂了这个,后面的属性都是顺理成章的。
2.1 什么是主轴和交叉轴?
想象你在纸上画了一条横线,一条竖线:
交叉轴(Cross Axis)
↑
|
|
──────────┼──────────→ 主轴(Main Axis)
|
|
↓- 主轴:子元素排列的方向(默认是水平方向,从左到右)
- 交叉轴:与主轴垂直的方向(默认是竖直方向,从上到下)
💡 大白话:主轴就是子元素「排队的方向」,交叉轴就是「垂直于排队的方向」。
2.2 改变主轴方向
用 flex-direction 可以改变主轴方向:
.box {
display: flex;
/* 1. 从左到右排列(默认值) */
flex-direction: row;
/* 2. 从右到左排列 */
flex-direction: row-reverse;
/* 3. 从上到下排列(主轴变成竖直方向) */
flex-direction: column;
/* 4. 从下到上排列 */
flex-direction: column-reverse;
}用图来表示就是:
row(默认) column
┌──────────────┐ ┌──────┐
│ [1] [2] [3] │ │ [1] │
└──────────────┘ │ [2] │
│ [3] │
└──────┘💡 记忆技巧:
row= 行 = 水平排列column= 列 = 垂直排列- 加上
-reverse就是反过来
三、容器属性(写在父元素上的属性)
接下来学习的属性都写在父元素(设置了 display: flex 的元素)上。
3.1 justify-content(主轴对齐)
这个属性控制子元素在主轴上怎么对齐。这是最常用的属性之一!
.box {
display: flex;
/* 1. 靠左排列(默认值) */
justify-content: flex-start;
/* 2. 靠右排列 */
justify-content: flex-end;
/* 3. 居中排列 */
justify-content: center;
/* 4. 两端对齐,中间等分 */
justify-content: space-between;
/* 5. 完全等分(每个元素左右间距一样) */
justify-content: space-evenly;
/* 6. 间距相同,首尾间距是中间的一半 */
justify-content: space-around;
}用图来表示(假设容器宽度比子元素总宽度大):
flex-start center space-between
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│[1][2][3] │ │ [1][2][3] │ │[1] [2] [3] │
└──────────────┘ └──────────────┘ └──────────────┘
space-evenly space-around
┌──────────────┐ ┌──────────────┐
│ [1] [2] [3] │ │[1] [2] [3] │
└──────────────┘ └──────────────┘💡 最常用的是哪几个?
center:水平居中space-between:导航栏菜单两端对齐space-evenly:均匀分布
3.2 align-items(交叉轴对齐)
这个属性控制子元素在交叉轴(垂直方向)上怎么对齐。
.box {
display: flex;
height: 200px; /* 容器要有高度才能看到效果 */
/* 1. 靠上对齐 */
align-items: flex-start;
/* 2. 靠下对齐 */
align-items: flex-end;
/* 3. 垂直居中 */
align-items: center;
/* 4. 拉伸填满(默认值) */
align-items: stretch;
/* 5. 文字基线对齐 */
align-items: baseline;
}用图来表示:
flex-start center flex-end
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│[1] [2] [3] │ │ │ │ │
│ │ │[1] [2] [3] │ │ │
│ │ │ │ │[1] [2] [3] │
└──────────────┘ └──────────────┘ └──────────────┘💡 最常用的场景:
align-items: center让子元素垂直居中!
3.3 完美居中(最经典用法)
水平居中 + 垂直居中 = 完美居中,只要两行代码:
.box {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 200px; /* 容器要有高度 */
}┌──────────────┐
│ │
│ │
│ [盒子] │ ← 水平和垂直都居中了!
│ │
│ │
└──────────────┘💡 以前没有 Flexbox 的时候,垂直居中是 CSS 最头疼的问题之一,各种 hack 层出不穷。现在有了 Flexbox,两行代码搞定!
3.4 flex-wrap(是否换行)
默认情况下,Flexbox 的子元素会挤在一行里,不会换行:
.box {
display: flex;
/* 1. 不换行,挤在一起(默认值) */
flex-wrap: nowrap;
/* 2. 放不下就换行 */
flex-wrap: wrap;
/* 3. 换行,但顺序反过来 */
flex-wrap: wrap-reverse;
}nowrap(默认) wrap
┌──────────────┐ ┌──────────────┐
│[1][2][3][4]5]│ │[1] [2] [3] │
└──────────────┘ │[4] [5] │
↑ 第5个被挤扁了 └──────────────┘💡 实际开发建议:大多数情况下设置为
flex-wrap: wrap,防止子元素被挤压变形。
3.5 flex-flow(简写)
flex-flow 是 flex-direction 和 flex-wrap 的简写:
/* 等价于 flex-direction: row; flex-wrap: wrap; */
.box {
display: flex;
flex-flow: row wrap;
}
/* 等价于 flex-direction: column; flex-wrap: nowrap; */
.box {
display: flex;
flex-flow: column nowrap;
}3.6 align-content(多行对齐)
当子元素换行后有多行时,align-content 控制行与行之间的间距:
.box {
display: flex;
flex-wrap: wrap; /* 必须允许换行 */
height: 300px; /* 容器要有足够高度 */
/* 多行之间两端对齐 */
align-content: space-between;
/* 多行整体居中 */
align-content: center;
/* 多行之间均匀分布 */
align-content: space-evenly;
}💡 注意:
align-content只在换行(flex-wrap: wrap)且有多行时才有效。如果只有一行,这个属性不起作用。
3.7 gap(间距)
这是一个非常实用的新属性,可以直接设置子元素之间的间距:
.box {
display: flex;
gap: 16px; /* 所有方向间距 16px */
/* 或者分别设置 */
row-gap: 16px; /* 行间距 */
column-gap: 24px; /* 列间距 */
}💡 以前我们常用 margin 来设置间距,但 margin 会有「最后一个元素也有外边距」的问题。用
gap就完美解决了!
四、子元素属性(写在子元素上的属性)
接下来学习的属性写在子元素上。
4.1 flex-grow(放大比例)
控制子元素在有剩余空间时,如何分配多余的空间。
.item1 {
/* 默认值 0,不放大 */
flex-grow: 0;
}
.item2 {
/* 占据所有剩余空间 */
flex-grow: 1;
}
.item3 {
/* 和 item2 平分剩余空间 */
flex-grow: 1;
}通俗理解:假设容器有 100px 剩余空间,如果两个子元素分别设置 flex-grow: 1 和 flex-grow: 3,那么它们会按照 1:3 的比例分配剩余空间(一个拿 25px,另一个拿 75px)。
没有 flex-grow item2: flex-grow: 1
┌──────────────────┐ ┌──────────────────┐
│[1] [2] [3] │ │[1] [2 3] │
└──────────────────┘ └──────────────────┘
↑ 右边有空余空间 ↑ item2 自动撑满了剩余空间💡 常见用法:侧边栏固定宽度 + 内容区
flex-grow: 1自动撑满
4.2 flex-shrink(缩小比例)
控制子元素在空间不够时,如何缩小。默认值是 1(会等比缩小)。
.sidebar {
/* 设置为 0,表示不缩小 */
flex-shrink: 0;
width: 200px; /* 侧边栏固定 200px */
}
.content {
/* 默认值 1,会自动缩小 */
flex-shrink: 1;
flex-grow: 1; /* 同时允许放大 */
}💡 常见用法:侧边栏
flex-shrink: 0防止被挤压
4.3 flex-basis(基础尺寸)
设置子元素在主轴上的初始大小,优先级高于 width(或 height)。
.item {
/* 像 width 一样用 */
flex-basis: 200px;
/* 根据内容自动撑开 */
flex-basis: auto; /* 默认值 */
/* 根据内容计算 */
flex-basis: content;
/* 也可以用百分比 */
flex-basis: 50%;
}💡 大白话:
flex-basis就是「在放大或缩小之前,子元素应该有多大」。
4.4 flex(简写,最常用!)
flex 是 flex-grow、flex-shrink、flex-basis 的简写,实际开发中最常用:
/* 最常用的写法 */
.item {
flex: 1; /* 等价于 flex: 1 1 0% */
}
/* 固定不放大不缩小 */
.sidebar {
flex: 0 0 200px; /* 等价于 flex-grow:0; flex-shrink:0; flex-basis:200px */
}
/* 只放大不缩小 */
.content {
flex: 1 0 auto;
}常用的 flex 值速查表:
| 写法 | 含义 | 适用场景 |
|---|---|---|
flex: 0 1 auto | 默认值,不放大但可缩小 | 普通元素 |
flex: 1 | 放大填满剩余空间 | 内容区 |
flex: 0 0 200px | 固定 200px 不变 | 侧边栏 |
flex: none | 不放大不缩小 | 固定尺寸元素 |
💡 实际开发建议:直接用
flex: 1或flex: 0 0 xxxpx就够了,不用单独写三个属性。
4.5 order(排序)
用 order 可以改变子元素的显示顺序,不需要改 HTML:
.item1 { order: 3; } /* 排第3 */
.item2 { order: 1; } /* 排第1 */
.item3 { order: 2; } /* 排第2 */
/* 显示顺序:item2 → item3 → item1 */💡 默认值是 0,值越小越靠前。可以用负数让它排到最前面。
4.6 align-self(单独对齐)
align-self 可以让某个子元素单独设置交叉轴对齐方式,覆盖父元素的 align-items:
.box {
display: flex;
align-items: center; /* 所有子元素垂直居中 */
}
.special-item {
align-self: flex-start; /* 但这个特殊元素靠上对齐 */
}五、实战练习
5.1 练习一:导航栏
最经典的 Flexbox 应用——导航栏布局:
<nav class="navbar">
<div class="logo">我的网站</div>
<div class="menu">
<a href="#">首页</a>
<a href="#">产品</a>
<a href="#">关于</a>
<a href="#">联系</a>
</div>
<button class="login">登录</button>
</nav>.navbar {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: space-between; /* 两端对齐 */
padding: 0 20px;
height: 60px;
background: #1a1a2e;
color: white;
}
.logo {
font-size: 20px;
font-weight: bold;
}
.menu {
display: flex;
gap: 20px; /* 菜单项之间的间距 */
}
.menu a {
color: white;
text-decoration: none;
}
.login {
padding: 8px 20px;
background: #4a90d9;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}效果: Logo 在左边,菜单在中间,登录按钮在右边,全部垂直居中。
5.2 练习二:卡片居中
让一个卡片在页面正中间显示:
<div class="page">
<div class="card">
<h2>欢迎登录</h2>
<input type="text" placeholder="用户名">
<input type="password" placeholder="密码">
<button>登录</button>
</div>
</div>.page {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
min-height: 100vh; /* 至少占满整个屏幕高度 */
background: #f0f2f5;
}
.card {
background: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
width: 360px;
display: flex;
flex-direction: column; /* 子元素竖向排列 */
gap: 16px; /* 子元素间距 16px */
}
.card input {
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
.card button {
padding: 10px;
background: #4a90d9;
color: white;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
}5.3 练习三:侧边栏 + 内容区
经典的后台管理布局:
<div class="layout">
<aside class="sidebar">
<div class="menu-item">仪表盘</div>
<div class="menu-item">用户管理</div>
<div class="menu-item">系统设置</div>
</aside>
<main class="content">
<h1>欢迎回来</h1>
<p>这里是内容区域,会自动撑满剩余空间。</p>
</main>
</div>.layout {
display: flex;
min-height: 100vh;
}
.sidebar {
flex: 0 0 240px; /* 固定 240px,不放大不缩小 */
background: #1a1a2e;
color: white;
padding: 20px 0;
}
.menu-item {
padding: 12px 24px;
cursor: pointer;
}
.menu-item:hover {
background: rgba(255, 255, 255, 0.1);
}
.content {
flex: 1; /* 自动撑满剩余空间 */
padding: 24px;
background: #f5f5f5;
}5.4 练习四:按钮组
几个按钮紧挨着排成一行:
<div class="button-group">
<button>取消</button>
<button>上一步</button>
<button class="primary">下一步</button>
</div>.button-group {
display: flex;
gap: 8px; /* 按钮之间 8px 间距 */
}
.button-group button {
padding: 8px 16px;
border: 1px solid #ddd;
border-radius: 6px;
background: white;
cursor: pointer;
}
.button-group .primary {
background: #4a90d9;
color: white;
border-color: #4a90d9;
}5.5 练习五:响应式卡片列表
卡片自动换行,每行显示固定数量:
<div class="card-list">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
<div class="card">卡片4</div>
<div class="card">卡片5</div>
<div class="card">卡片6</div>
</div>.card-list {
display: flex;
flex-wrap: wrap; /* 允许换行 */
gap: 16px; /* 卡片间距 */
}
.card {
/* 每行3个卡片,减去间距 */
width: calc((100% - 32px) / 3);
height: 150px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
/* 响应式:小屏幕每行2个 */
@media (max-width: 768px) {
.card {
width: calc((100% - 16px) / 2);
}
}
/* 手机屏幕每行1个 */
@media (max-width: 480px) {
.card {
width: 100%;
}
}六、常见问题
6.1 为什么我的 flex: 1 不生效?
/* 问题:父元素没有设置 display: flex */
.parent {
/* 忘了加这一行! */
/* display: flex; */
}
.child {
flex: 1; /* 不生效,因为父元素不是 flex 容器 */
}解决: 确保父元素设置了 display: flex。
6.2 为什么 align-items: center 不生效?
/* 问题:父元素没有高度 */
.box {
display: flex;
align-items: center;
/* 没有设置 height,父元素高度等于子元素高度,看不出居中效果 */
}
/* 解决:给父元素设置高度 */
.box {
display: flex;
align-items: center;
height: 200px; /* 现在能看出来了 */
}6.3 flex-basis 和 width 有什么区别?
/* flex-basis 优先级更高 */
.item {
flex-basis: 200px;
width: 100px; /* 会被忽略,实际宽度是 200px */
}
/* 如果主轴是竖直方向(flex-direction: column),
flex-basis 控制的是高度,width 控制的是宽度 */
.column-box {
display: flex;
flex-direction: column;
}
.column-box .item {
flex-basis: 100px; /* 这是高度 */
width: 200px; /* 这是宽度 */
}6.4 子元素被挤扁了怎么办?
/* 问题:子元素内容太多被挤压变形 */
.box {
display: flex;
/* 默认 flex-shrink: 1,会缩小 */
}
/* 解决:禁止缩小 */
.box .item {
flex-shrink: 0; /* 不再缩小 */
/* 或者 */
flex: 0 0 auto; /* 不放大、不缩小、按内容大小 */
}七、Flexbox 速查表
7.1 父元素属性
| 属性 | 作用 | 常用值 |
|---|---|---|
display | 开启弹性布局 | flex |
flex-direction | 排列方向 | row / column |
justify-content | 主轴对齐 | center / space-between |
align-items | 交叉轴对齐 | center / flex-start |
flex-wrap | 是否换行 | wrap |
gap | 子元素间距 | 16px |
align-content | 多行间距 | space-between |
7.2 子元素属性
| 属性 | 作用 | 常用值 |
|---|---|---|
flex | 放大/缩小/基础尺寸 | 1 / 0 0 200px |
order | 排序 | 数字(默认 0) |
align-self | 单独对齐 | center / flex-start |
7.3 最常用组合
| 场景 | CSS |
|---|---|
| 水平垂直居中 | display:flex; justify-content:center; align-items:center; |
| 两端对齐 | display:flex; justify-content:space-between; |
| 侧边栏+内容 | 侧边栏 flex:0 0 240px;,内容区 flex:1; |
| 垂直排列 | display:flex; flex-direction:column; |
| 卡片换行 | display:flex; flex-wrap:wrap; gap:16px; |
八、总结
让我们回顾一下这篇教程的要点:
display: flex写在父元素上,开启弹性布局- 主轴是子元素排列方向,交叉轴是垂直方向
justify-content控制主轴对齐(水平方向)align-items控制交叉轴对齐(垂直方向)flex: 1让子元素撑满剩余空间flex-wrap: wrap让子元素放不下时自动换行gap设置子元素间距,比 margin 更好用- 完美居中只需要
justify-content: center+align-items: center
记住这些,日常开发中 90% 的布局问题都能解决了!
相关阅读: