CSS3 Flexbox 布局完全指南

小飞兽 HTML/CSS 342 次阅读 2026-04-27

引言

在 CSS3 出现之前,网页布局几乎完全依赖 float(浮动)和 position(定位)来实现。然而,浮动设计初衷是用于文字环绕图片,清除浮动带来的副作用令无数开发者头疼;而绝对定位虽然精确,却会使元素脱离文档流,导致响应式布局极其困难。CSS3 引入的 Flexbox(弹性盒布局)模块彻底改变了这一困境——它提供了一种更加高效、更加直观的方式来排列、对齐和分配容器内元素的空间,即使这些元素的大小未知或是动态变化的。Flexbox 的设计理念是"让容器决定如何分配空间,而不是让每个子元素自己决定位置"。本文将全面介绍 Flexbox 的工作原理、核心属性和实战技巧,帮助你掌握现代 CSS 布局的利器。

一、基础语法

1. 核心概念:弹性容器与弹性项目

使用 Flexbox 只需两步:

/* 第一步:将父容器设置为弹性容器 */
.container {
  display: flex;  /* 或 display: inline-flex; */
}

一旦设置了 display: flex,该容器就成为了弹性容器(Flex Container),它的直接子元素自动成为弹性项目(Flex Items)。弹性项目会沿着一个隐式的主轴(Main Axis)排列。

2. 主轴与交叉轴

  • <strong>主轴(Main Axis)</strong>:弹性项目排列的主要方向,由 <code>flex-direction</code> 属性决定,默认从左到右(row)。
  • <strong>交叉轴(Cross Axis)</strong>:垂直于主轴的方向,用于定义项目在垂直方向上的对齐方式。
# 主轴为 row(默认)时的轴向示意:

← main axis →
┌─────────────────────────────┐
│  项目1  │  项目2  │  项目3  │  ↑ cross axis
└─────────────────────────────┘

3. 核心属性速览

容器侧属性(控制整体布局):

| 属性 | 说明 |
|------|------|
| flex-direction | 主轴方向:row / row-reverse / column / column-reverse |
| flex-wrap | 换行策略:nowrap / wrap / wrap-reverse |
| flex-flow | flex-direction 和 flex-wrap 的简写 |
| justify-content | 主轴上的对齐方式 |
| align-items | 交叉轴上所有项目的对齐方式(单行) |
| align-content | 交叉轴上多根轴线的对齐方式(多行) |
| gap | 弹性项目之间的间距 |

项目侧属性(控制单个项目行为):

| 属性 | 说明 |
|------|------|
| flex-grow | 放大比例(默认为 0,不放大) |
| flex-shrink | 缩小比例(默认为 1,可缩小) |
| flex-basis | 初始主轴尺寸(默认 auto) |
| flex | 上述三个属性的简写(推荐写法) |
| align-self | 单独覆盖容器的 align-items |
| order | 项目的排列顺序(数值越小越靠前) |

二、代码示例

1. 水平居中布局(最常用场景)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Flexbox 水平垂直居中</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }

  .parent {
    display: flex;
    justify-content: center;   /* 主轴居中 */
    align-items: center;      /* 交叉轴居中 */
    height: 100vh;            /* 全屏高度 */
    background: #1a1a2e;
  }

  .child {
    width: 300px;
    padding: 40px;
    background: #e94560;
    color: #fff;
    text-align: center;
    border-radius: 12px;
    font-size: 18px;
  }
</style>
</head>
<body>
<div class="parent">
  <div class="child">
    水平垂直居中<br>
    仅用两行 Flexbox 代码实现
  </div>
</div>
</body>
</html>

运行效果:深色背景容器中,一个粉红色卡片精准地水平垂直居中于页面正中央。

2. 响应式导航栏

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Flexbox 响应式导航栏</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }

  nav {
    display: flex;
    justify-content: space-between; /* LOGO 靠左,链接靠右 */
    align-items: center;
    padding: 0 30px;
    height: 60px;
    background: #16213e;
    color: #fff;
  }

  .logo {
    font-size: 20px;
    font-weight: bold;
    color: #e94560;
  }

  .links {
    display: flex;
    gap: 20px;               /* 链接之间 20px 间距 */
    list-style: none;
  }

  .links a {
    color: #fff;
    text-decoration: none;
    padding: 8px 16px;
    border-radius: 4px;
    transition: background 0.3s;
  }

  .links a:hover {
    background: #e94560;
  }

  @media (max-width: 600px) {
    nav {
      flex-direction: column;  /* 移动端改为纵向排列 */
      height: auto;
      padding: 15px;
      gap: 15px;
    }
    .links {
      flex-direction: column;
      align-items: center;
      width: 100%;
    }
  }
</style>
</head>
<body>
<nav>
  <div class="logo">MySite</div>
  <ul class="links">
    <li><a href="#">首页</a></li>
    <li><a href="#">产品</a></li>
    <li><a href="#">案例</a></li>
    <li><a href="#">关于</a></li>
  </ul>
</nav>
</body>
</html>

运行效果:桌面端 LOGO 左侧、导航链接右侧均匀分布;移动端(屏幕宽度 ≤600px)自动变为垂直堆叠布局。

3. 圣杯布局(Holy Grail Layout)

圣杯布局是经典的三栏布局——两侧固定宽度,中间内容区自适应,是 Flexbox 最能体现其强大能力的场景:

.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header {
  background: #16213e;
  color: #fff;
  padding: 20px;
}

.main {
  display: flex;
  flex: 1; /* 自动填充剩余高度 */
}

.sidebar-left,
.sidebar-right {
  width: 200px;
  background: #eaeaea;
  padding: 20px;
}

.content {
  flex: 1;            /* 中间栏自动占满剩余空间 */
  padding: 20px;
  background: #fafafa;
}

.footer {
  background: #16213e;
  color: #fff;
  padding: 20px;
}
<div class="page">
  <header class="header">页眉</header>
  <div class="main">
    <aside class="sidebar-left">左侧栏</aside>
    <main class="content">主内容区(自动填充剩余空间)</main>
    <aside class="sidebar-right">右侧栏</aside>
  </div>
  <footer class="footer">页脚</footer>
</div>

4. 弹性项目的高级用法

/* 等分三列,响应式两列,单列 */
.card-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  /* flex: 1 1 300px 含义:
     grow=1(可放大)shrink=1(可缩小)basis=300px
     效果:优先三列,不够时缩小到 300px,再不够则换行
  */
  flex: 1 1 300px;
  background: #fff;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* 单独让某个项目靠上对齐 */
.card.tall {
  align-self: flex-start;
}

/* 调整排列顺序 */
.card.first {
  order: -1;  /* 最靠前显示 */
}

三、运行效果

在浏览器中打开上述三个示例,你将看到:

  • <strong>水平垂直居中</strong>:一个彩色卡片在深色背景中完美居中,无论浏览器窗口如何缩放,卡片始终保持在视口正中央。

  • <strong>响应式导航栏</strong>:桌面端 LOGO 和链接在水平行两端分布;缩小窗口至 600px 以下时,链接自动变为垂直堆叠,布局完全自适应,无需 JavaScript。

  • <strong>圣杯布局</strong>:页眉和页脚占据固定高度,内容区三栏排列,两侧栏 200px 固定宽度,中间内容区自动占满剩余空间且高度撑满屏幕。

  • <strong>弹性卡片组</strong>:卡片自动沿主轴排列,每行尽量放下三个(每列最小 300px),空间不足时自动换行。

四、常见问题

Q1:flex-grow 和 flex-shrink 的值具体如何计算?

flex-grow 表示当容器有剩余空间时,项目按比例"瓜分"剩余空间。假设三个项目 grow 分别为 1、2、1,总和为 4,则剩余空间除以 4,每个 grow=1 的项目各得 1 份,grow=2 的项目得 2 份。

flex-shrink 相反,表示当容器空间不足时,项目按比例"分担"亏空。计算更为复杂,需要考虑 flex-basis(即项目的基准尺寸)。通常 flex-shrink: 1(默认值)意味着允许项目被压缩。

Q2:flex-basis 和 width/height 有什么区别?

flex-basis 定义的是项目在主轴方向上的初始尺寸,当 flex-direction: row 时它等同于 width,当 flex-direction: column 时等同于 height。但关键区别在于:当设置了 flex-grow/shrink 时,flex-basis 的优先级高于 width/height。

Q3:justify-content 和 align-items 总是混淆怎么办?

记忆技巧:"justify" 的 J 长得像横向的 I,所以处理水平方向(主轴);"align" 没有 J,处理垂直方向(交叉轴)。

Q4:flex-wrap: wrap 和 flex: 1 1 auto 一起用时项目溢出怎么办?

flex-basis 之和超过容器宽度时,即使设置了 flex-wrap: wrap,flex 项目也不会自动收缩到容器内(因为 flex-shrink 默认为 1)。如果出现溢出,检查是否有项目设置了 flex-basis 过大或 flex-shrink: 0

Q5:如何让 Flexbox 布局在 IE11 中正常工作?

IE11 对 Flexbox 的支持存在不少 Bug,常见问题包括:

  • <code>flex-basis: 0</code> 在 IE11 中需要写为 <code>flex-basis: 0px</code>(明确带单位);

  • <code>align-items: baseline</code> 在某些场景下失效,建议使用 <code>margin-top</code> 或 <code>padding-top</code> 替代;

  • 建议使用 <code>display: -ms-flexbox</code> 前缀或使用 Autoprefixer 插件自动补全。

Q6:flex: 1 和 flex: auto 哪个更好?

  • <code>flex: 1</code> 是 <code>flex: 1 1 0%</code> 的简写,基准尺寸为 0,项目完全按比例分配空间。
  • <code>flex: auto</code> 是 <code>flex: 1 1 auto</code> 的简写,基准尺寸为项目自身内容宽度,会优先保留内容所需空间再分配剩余空间。

如果希望所有项目均匀分配空间,用 flex: 1;如果希望项目保持内容所需尺寸但仍可分配剩余空间,用 flex: auto

五、延伸阅读

1. MDN Flexbox 完整指南https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout — 最权威的 Flexbox 官方文档,包含详细图示。
2. Flexbox Froggyhttps://flexboxfroggy.com/ — 通过一个青蛙游戏练习 Flexbox 属性,趣味性强,适合初学者。
3. CSS-Tricks Complete Guide to Flexboxhttps://css-tricks.com/snippets/css/a-guide-to-flexbox/ — 几乎每个前端开发者都收藏过的 Flexbox 速查表,图文并茂。
4. Autoprefixerhttps://autoprefixer.github.io/ — 自动为 CSS 添加浏览器前缀,确保 Flexbox 在旧版浏览器中的兼容性。
5. 《CSS 权威指南(第四版)》:人民邮电出版社,Eric A. Meyer 著,CSS 领域最经典的参考书,覆盖 Flexbox 等现代布局模块。
6. Can I Use - Flexboxhttps://caniuse.com/flexbox — 实时查询全球各浏览器版本对 Flexbox 的支持率和使用情况。