跳转到内容

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

CSS Flexbox 弹性布局从零到精通

你是否曾被网页布局搞得焦头烂额?用 float 排版总是错位,用 position 定位又总是对不齐?别担心,Flexbox(弹性布局)就是来拯救你的!这篇教程会从零开始,用大白话带你彻底搞懂 Flexbox。


一、什么是 Flexbox?

1.1 通俗理解

想象你有一个纸箱子(容器),里面放着几本书(子元素):

  • 不用 Flexbox:书随便乱放,你很难控制它们的位置
  • 用 Flexbox:你可以让书整齐排列、自动等间距、自动居中、自动撑满空间

一句话总结:Flexbox 就是让容器里的子元素「听话地排列」的一种布局方式。

1.2 什么时候用 Flexbox?

场景例子
水平居中一个按钮在导航栏中间
垂直居中文字在卡片正中间
等间距排列导航菜单的几个链接等距排开
自适应宽度侧边栏固定宽度,内容区自动撑满
按钮组几个按钮紧挨着排成一行

1.3 最简单的例子

先来个最简单的例子,感受一下 Flexbox 的魔力:

html
<!-- HTML -->
<div class="box">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
css
/* 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 可以改变主轴方向:

css
.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(主轴对齐)

这个属性控制子元素在主轴上怎么对齐。这是最常用的属性之一!

css
.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(交叉轴对齐)

这个属性控制子元素在交叉轴(垂直方向)上怎么对齐。

css
.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 完美居中(最经典用法)

水平居中 + 垂直居中 = 完美居中,只要两行代码:

css
.box {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  height: 200px;            /* 容器要有高度 */
}
┌──────────────┐
│              │
│              │
│    [盒子]    │  ← 水平和垂直都居中了!
│              │
│              │
└──────────────┘

💡 以前没有 Flexbox 的时候,垂直居中是 CSS 最头疼的问题之一,各种 hack 层出不穷。现在有了 Flexbox,两行代码搞定!

3.4 flex-wrap(是否换行)

默认情况下,Flexbox 的子元素会挤在一行里,不会换行:

css
.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-flowflex-directionflex-wrap 的简写:

css
/* 等价于 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 控制行与行之间的间距:

css
.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(间距)

这是一个非常实用的新属性,可以直接设置子元素之间的间距:

css
.box {
  display: flex;
  gap: 16px;              /* 所有方向间距 16px */
  /* 或者分别设置 */
  row-gap: 16px;          /* 行间距 */
  column-gap: 24px;       /* 列间距 */
}

💡 以前我们常用 margin 来设置间距,但 margin 会有「最后一个元素也有外边距」的问题。用 gap 就完美解决了!


四、子元素属性(写在子元素上的属性)

接下来学习的属性写在子元素上。

4.1 flex-grow(放大比例)

控制子元素在有剩余空间时,如何分配多余的空间。

css
.item1 {
  /* 默认值 0,不放大 */
  flex-grow: 0;
}

.item2 {
  /* 占据所有剩余空间 */
  flex-grow: 1;
}

.item3 {
  /* 和 item2 平分剩余空间 */
  flex-grow: 1;
}

通俗理解:假设容器有 100px 剩余空间,如果两个子元素分别设置 flex-grow: 1flex-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(会等比缩小)。

css
.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)。

css
.item {
  /* 像 width 一样用 */
  flex-basis: 200px;

  /* 根据内容自动撑开 */
  flex-basis: auto;  /* 默认值 */

  /* 根据内容计算 */
  flex-basis: content;

  /* 也可以用百分比 */
  flex-basis: 50%;
}

💡 大白话flex-basis 就是「在放大或缩小之前,子元素应该有多大」。

4.4 flex(简写,最常用!)

flexflex-growflex-shrinkflex-basis 的简写,实际开发中最常用

css
/* 最常用的写法 */
.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: 1flex: 0 0 xxxpx 就够了,不用单独写三个属性。

4.5 order(排序)

order 可以改变子元素的显示顺序,不需要改 HTML

css
.item1 { order: 3; }  /* 排第3 */
.item2 { order: 1; }  /* 排第1 */
.item3 { order: 2; }  /* 排第2 */

/* 显示顺序:item2 → item3 → item1 */

💡 默认值是 0,值越小越靠前。可以用负数让它排到最前面。

4.6 align-self(单独对齐)

align-self 可以让某个子元素单独设置交叉轴对齐方式,覆盖父元素的 align-items

css
.box {
  display: flex;
  align-items: center;  /* 所有子元素垂直居中 */
}

.special-item {
  align-self: flex-start;  /* 但这个特殊元素靠上对齐 */
}

五、实战练习

5.1 练习一:导航栏

最经典的 Flexbox 应用——导航栏布局:

html
<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>
css
.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 练习二:卡片居中

让一个卡片在页面正中间显示:

html
<div class="page">
  <div class="card">
    <h2>欢迎登录</h2>
    <input type="text" placeholder="用户名">
    <input type="password" placeholder="密码">
    <button>登录</button>
  </div>
</div>
css
.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 练习三:侧边栏 + 内容区

经典的后台管理布局:

html
<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>
css
.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 练习四:按钮组

几个按钮紧挨着排成一行:

html
<div class="button-group">
  <button>取消</button>
  <button>上一步</button>
  <button class="primary">下一步</button>
</div>
css
.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 练习五:响应式卡片列表

卡片自动换行,每行显示固定数量:

html
<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>
css
.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 不生效?

css
/* 问题:父元素没有设置 display: flex */
.parent {
  /* 忘了加这一行! */
  /* display: flex; */
}

.child {
  flex: 1;  /* 不生效,因为父元素不是 flex 容器 */
}

解决: 确保父元素设置了 display: flex

6.2 为什么 align-items: center 不生效?

css
/* 问题:父元素没有高度 */
.box {
  display: flex;
  align-items: center;
  /* 没有设置 height,父元素高度等于子元素高度,看不出居中效果 */
}

/* 解决:给父元素设置高度 */
.box {
  display: flex;
  align-items: center;
  height: 200px;  /* 现在能看出来了 */
}

6.3 flex-basis 和 width 有什么区别?

css
/* 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 子元素被挤扁了怎么办?

css
/* 问题:子元素内容太多被挤压变形 */
.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;

八、总结

让我们回顾一下这篇教程的要点:

  1. display: flex 写在父元素上,开启弹性布局
  2. 主轴是子元素排列方向,交叉轴是垂直方向
  3. justify-content 控制主轴对齐(水平方向)
  4. align-items 控制交叉轴对齐(垂直方向)
  5. flex: 1 让子元素撑满剩余空间
  6. flex-wrap: wrap 让子元素放不下时自动换行
  7. gap 设置子元素间距,比 margin 更好用
  8. 完美居中只需要 justify-content: center + align-items: center

记住这些,日常开发中 90% 的布局问题都能解决了!


相关阅读: