返回文章列表

CSS Flexbox 弹性布局完全指南

Flexbox(弹性盒子布局)是 CSS3 中一种强大的一维布局模型。它能够高效地排列、对齐和分配容器内元素的空间,即使元素的大小未知或是动态变化的。本文将全面讲解 Flexbox 的核心概念、容器属性、项目属性,并通过多个实战案例帮助你真正掌握它。

一、Flexbox 基本概念

Flexbox 布局由两个核心部分组成:

Flexbox 采用主轴(Main Axis)和交叉轴(Cross Axis)的双轴模型:

<!-- 基本结构 -->
<div class="flex-container">
    <div class="flex-item">项目 1</div>
    <div class="flex-item">项目 2</div>
    <div class="flex-item">项目 3</div>
</div>

<style>
.flex-container {
    display: flex;  /* 启用 Flexbox 布局 */
    /* 也可以使用 inline-flex,使容器本身成为行内元素 */
}
</style>

二、容器属性

容器属性作用于 Flex 容器(父元素),控制项目的排列方式和分布。

2.1 flex-direction:主轴方向

flex-direction 定义主轴的方向,即项目的排列方向:

.flex-container {
    display: flex;

    /* 默认值:从左到右 */
    flex-direction: row;

    /* 从右到左 */
    flex-direction: row-reverse;

    /* 从上到下 */
    flex-direction: column;

    /* 从下到上 */
    flex-direction: column-reverse;
}

2.2 justify-content:主轴对齐

justify-content 定义项目在主轴上的对齐方式和剩余空间的分配:

.flex-container {
    display: flex;
    justify-content: flex-start;    /* 默认值,左对齐 */
    /* justify-content: flex-end;        右对齐 */
    /* justify-content: center;          居中 */
    /* justify-content: space-between;   两端对齐,项目之间间距相等 */
    /* justify-content: space-around;    每个项目两侧间距相等 */
    /* justify-content: space-evenly;    所有间距完全相等 */
}

2.3 align-items:交叉轴对齐

align-items 定义项目在交叉轴上的对齐方式:

.flex-container {
    display: flex;
    height: 300px;

    /* 默认值:拉伸以填满容器 */
    align-items: stretch;

    /* align-items: flex-start;   顶部对齐 */
    /* align-items: flex-end;     底部对齐 */
    /* align-items: center;       垂直居中 */
    /* align-items: baseline;    按第一行文字基线对齐 */
}

2.4 flex-wrap:换行控制

flex-wrap 控制项目是否换行:

.flex-container {
    display: flex;

    /* 默认值:不换行,项目会缩小以适应容器 */
    flex-wrap: nowrap;

    /* flex-wrap: wrap;          换行,第一行在上 */
    /* flex-wrap: wrap-reverse;  换行,第一行在下 */
}

/* 可以与 flex-direction 合并为简写属性 flex-flow */
.flex-container {
    display: flex;
    flex-flow: row wrap;  /* 等价于 flex-direction: row; flex-wrap: wrap; */
}

2.5 align-content:多行对齐

align-content 定义多行项目在交叉轴上的对齐方式(仅在有多行时生效):

.flex-container {
    display: flex;
    flex-wrap: wrap;
    height: 500px;

    /* 默认值:各行拉伸填满 */
    align-content: stretch;

    /* align-content: flex-start;     所有行紧贴容器顶部 */
    /* align-content: flex-end;       所有行紧贴容器底部 */
    /* align-content: center;         所有行居中 */
    /* align-content: space-between;  行与行之间间距相等 */
    /* align-content: space-around;   每行上下间距相等 */
    /* align-content: space-evenly;   所有间距完全相等 */
}

三、项目属性

项目属性作用于 Flex 项目(子元素),控制单个项目的行为。

3.1 flex-grow:放大比例

flex-grow 定义项目的放大比例,默认为 0(不放大)。当容器有剩余空间时,项目按比例分配:

.item-1 { flex-grow: 1; } /* 占 1 份剩余空间 */
.item-2 { flex-grow: 2; } /* 占 2 份剩余空间 */
.item-3 { flex-grow: 1; } /* 占 1 份剩余空间 */
/* 总共 4 份,item-2 的宽度是 item-1 的两倍 */

3.2 flex-shrink:缩小比例

flex-shrink 定义项目的缩小比例,默认为 1。当空间不足时,项目按比例缩小:

.item-1 {
    flex-shrink: 0; /* 不缩小,保持原始尺寸 */
    width: 200px;
}
.item-2 {
    flex-shrink: 2; /* 缩小速度是默认的两倍 */
    width: 200px;
}
.item-3 {
    flex-shrink: 1; /* 默认缩小速度 */
    width: 200px;
}

3.3 flex-basis:初始大小

flex-basis 定义项目在分配剩余空间之前的初始大小:

.item {
    flex-basis: auto;   /* 默认值,由内容或 width/height 决定 */
    /* flex-basis: 200px;  固定初始宽度 */
    /* flex-basis: 30%;     占容器的 30% */
    /* flex-basis: 0;       完全依赖 flex-grow 分配 */
}

3.4 flex 简写属性

flex 是 flex-grow、flex-shrink、flex-basis 的简写:

/* 完整写法 */
.item {
    flex: 0 1 auto; /* grow: 0, shrink: 1, basis: auto(默认值) */
}

/* 常用简写 */
.item {
    flex: 1;          /* 等价于 flex: 1 1 0% — 所有项目等分空间 */
}
.item {
    flex: auto;       /* 等价于 flex: 1 1 auto — 按内容比例分配 */
}
.item {
    flex: none;       /* 等价于 flex: 0 0 auto — 固定大小不缩放 */
}
.item {
    flex: 0 0 200px;  /* 固定为 200px,不放大也不缩小 */
}

/* 两个值的写法 */
.item {
    flex: 1 200px;    /* 等价于 flex: 1 1 200px */
}

3.5 order:排列顺序

order 定义项目的排列顺序,默认为 0,数值越小越靠前:

.item-1 { order: 3; }  /* 排在最后 */
.item-2 { order: 1; }  /* 排在第一位 */
.item-3 { order: 2; }  /* 排在第二位 */

3.6 align-self:单个项目对齐

align-self 允许单个项目覆盖容器的 align-items 设置:

.flex-container {
    display: flex;
    align-items: center; /* 所有项目垂直居中 */
}

.special-item {
    align-self: flex-start; /* 这个项目改为顶部对齐 */
    /* align-self: flex-end;    底部对齐 */
    /* align-self: stretch;     拉伸 */
    /* align-self: baseline;    基线对齐 */
    /* align-self: auto;        继承 align-items */
}

四、实战案例

4.1 导航栏布局

使用 Flexbox 实现一个经典的导航栏,Logo 在左,菜单居中,按钮在右:

<nav class="navbar">
    <div class="nav-logo">Logo</div>
    <ul class="nav-links">
        <li><a href="#">首页</a></li>
        <li><a href="#">关于</a></li>
        <li><a href="#">服务</a></li>
        <li><a href="#">联系</a></li>
    </ul>
    <button class="nav-btn">登录</button>
</nav>
.navbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    height: 64px;
    background: #1a1a2e;
    color: #fff;
}

.nav-logo {
    font-size: 20px;
    font-weight: bold;
    flex-shrink: 0; /* 不被压缩 */
}

.nav-links {
    display: flex;
    list-style: none;
    gap: 24px; /* 项目间距 */
    margin: 0;
    padding: 0;
}

.nav-links a {
    color: #ccc;
    text-decoration: none;
    transition: color 0.3s;
}

.nav-links a:hover {
    color: #ff6b6b;
}

.nav-btn {
    padding: 8px 20px;
    background: #ff6b6b;
    color: #fff;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    flex-shrink: 0;
}

/* 移动端适配 */
@media (max-width: 768px) {
    .nav-links {
        display: none; /* 移动端隐藏菜单 */
    }
}

4.2 响应式卡片布局

一个自适应的卡片网格,在大屏上一行三列,中屏两列,小屏一列:

<div class="card-container">
    <div class="card">
        <div class="card-image">图片</div>
        <h3>卡片标题</h3>
        <p>卡片描述文字...</p>
        <button>了解更多</button>
    </div>
    <div class="card">
        <div class="card-image">图片</div>
        <h3>卡片标题</h3>
        <p>卡片描述文字...</p>
        <button>了解更多</button>
    </div>
    <div class="card">
        <div class="card-image">图片</div>
        <h3>卡片标题</h3>
        <p>卡片描述文字...</p>
        <button>了解更多</button>
    </div>
    <div class="card">
        <div class="card-image">图片</div>
        <h3>卡片标题</h3>
        <p>卡片描述文字...</p>
        <button>了解更多</button>
    </div>
</div>
.card-container {
    display: flex;
    flex-wrap: wrap;
    gap: 20px; /* 卡片间距 */
    padding: 20px;
}

.card {
    flex: 1 1 300px; /* 最小宽度 300px,自动填充剩余空间 */
    max-width: calc(33.333% - 14px); /* 大屏最多三列 */
    background: #fff;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
}

.card-image {
    height: 200px;
    background: linear-gradient(135deg, #667eea, #764ba2);
}

.card h3 {
    padding: 16px 16px 0;
}

.card p {
    padding: 8px 16px;
    color: #666;
    flex: 1; /* 描述区域自动填充剩余高度 */
}

.card button {
    margin: 12px 16px 16px;
    padding: 10px 20px;
    background: #4ecdc4;
    color: #fff;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    align-self: flex-start; /* 按钮靠左 */
}

/* 中屏:最多两列 */
@media (max-width: 1024px) {
    .card {
        max-width: calc(50% - 10px);
    }
}

/* 小屏:单列 */
@media (max-width: 640px) {
    .card {
        max-width: 100%;
    }
}

4.3 完美居中方案

Flexbox 让居中变得极其简单,这是最常用的功能之一:

/* 水平 + 垂直居中(最常用) */
.center-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
}

/* 只水平居中 */
.horizontal-center {
    display: flex;
    justify-content: center;
}

/* 只垂直居中 */
.vertical-center {
    display: flex;
    align-items: center;
    min-height: 100vh;
}

/* 使用 margin: auto 居中单个元素 */
.parent {
    display: flex;
}

.child {
    margin: auto; /* 在两个轴上同时居中 */
}

4.4 圣杯布局(Holy Grail Layout)

经典的顶部导航 + 左侧边栏 + 主内容 + 右侧边栏 + 底部布局:

<div class="holy-grail">
    <header class="hg-header">顶部导航</header>
    <div class="hg-body">
        <aside class="hg-sidebar-left">左侧边栏</aside>
        <main class="hg-content">主内容区域</main>
        <aside class="hg-sidebar-right">右侧边栏</aside>
    </div>
    <footer class="hg-footer">底部</footer>
</div>
.holy-grail {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.hg-header {
    background: #1a1a2e;
    color: #fff;
    padding: 16px 24px;
    flex-shrink: 0; /* 头部不被压缩 */
}

.hg-body {
    display: flex;
    flex: 1; /* 占据剩余的全部空间 */
}

.hg-sidebar-left {
    width: 250px;
    background: #f0f0f0;
    padding: 20px;
    flex-shrink: 0; /* 侧边栏保持固定宽度 */
}

.hg-content {
    flex: 1; /* 主内容区域自动填充 */
    padding: 20px;
    overflow-y: auto;
}

.hg-sidebar-right {
    width: 200px;
    background: #f0f0f0;
    padding: 20px;
    flex-shrink: 0;
}

.hg-footer {
    background: #1a1a2e;
    color: #fff;
    padding: 16px 24px;
    text-align: center;
    flex-shrink: 0;
}

/* 响应式:小屏隐藏侧边栏 */
@media (max-width: 768px) {
    .hg-body {
        flex-direction: column;
    }
    .hg-sidebar-left,
    .hg-sidebar-right {
        width: 100%;
        display: none; /* 小屏隐藏侧边栏 */
    }
}

4.5 粘性底部(Sticky Footer)

当页面内容不足一屏时,页脚始终固定在底部:

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

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

.footer {
    flex-shrink: 0; /* 页脚不会被压缩 */
}

五、Flexbox 常见技巧

5.1 间距控制

使用 gap 属性(现代浏览器已广泛支持)可以轻松设置项目间距:

.container {
    display: flex;
    gap: 16px;           /* 行和列间距相同 */
    /* gap: 16px 24px; */ /* 行间距 16px,列间距 24px */
    /* row-gap: 16px;   */
    /* column-gap: 24px; */
}

/* 兼容方案(使用 margin) */
.container-legacy {
    display: flex;
}
.container-legacy > * {
    margin-right: 16px;
}
.container-legacy > *:last-child {
    margin-right: 0;
}

5.2 等分列布局

/* 三等分 */
.columns-3 {
    display: flex;
    gap: 16px;
}
.columns-3 > * {
    flex: 1;
}

/* 左侧固定,右侧自适应 */
.sidebar-layout {
    display: flex;
    gap: 20px;
}
.sidebar {
    width: 280px;
    flex-shrink: 0;
}
.main {
    flex: 1;
    min-width: 0; /* 防止 flex 项目溢出 */
}

六、总结

Flexbox 是现代 CSS 布局中不可或缺的工具,它极大地简化了一维布局的复杂度。通过本文的学习,你应该掌握了以下核心知识:

Flexbox 擅长处理一维布局(一行或一列)。对于更复杂的二维网格布局,建议配合 CSS Grid 使用。两者可以嵌套组合,发挥各自的优势。

动手挑战

学到这里,不妨动手试一试以下练习,巩固你的理解:

  1. 基础练习:回顾本文核心概念,用自己的话总结关键知识点。
  2. 进阶实践:将文中的示例代码运行一遍,尝试修改参数观察变化。
  3. 拓展思考:想一想这个技术/方法还能应用在哪些场景中?

小贴士:遇到问题时,先独立思考,再查阅资料,最后请教他人——这是成长最快的学习方式。

赞赏支持

本文更新于 2026-08-22,环境 Python 3.12