CSS Flexbox 弹性布局完全指南
Flexbox(弹性盒子布局)是 CSS3 中一种强大的一维布局模型。它能够高效地排列、对齐和分配容器内元素的空间,即使元素的大小未知或是动态变化的。本文将全面讲解 Flexbox 的核心概念、容器属性、项目属性,并通过多个实战案例帮助你真正掌握它。
一、Flexbox 基本概念
Flexbox 布局由两个核心部分组成:
- Flex 容器(Flex Container):设置了
display: flex或display: inline-flex的父元素 - Flex 项目(Flex Items):Flex 容器的直接子元素
Flexbox 采用主轴(Main Axis)和交叉轴(Cross Axis)的双轴模型:
- 主轴:Flex 项目排列的方向,默认为水平方向(从左到右)
- 交叉轴:与主轴垂直的方向,默认为垂直方向(从上到下)
<!-- 基本结构 -->
<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 的双轴模型概念(主轴与交叉轴)
- 容器属性:flex-direction、justify-content、align-items、flex-wrap、align-content
- 项目属性:flex-grow、flex-shrink、flex-basis、order、align-self
- flex 简写属性的常见用法
- 实战布局:导航栏、卡片网格、居中方案、圣杯布局、粘性底部
- 间距控制和等分布局技巧
Flexbox 擅长处理一维布局(一行或一列)。对于更复杂的二维网格布局,建议配合 CSS Grid 使用。两者可以嵌套组合,发挥各自的优势。