CSS Flexbox 弹性布局
Flexbox(弹性盒子布局)是 CSS 一维布局的核心方案。它能让你轻松地在一行或一列中排列元素,并自动处理对齐、分布和空间分配。
启用 Flexbox
将容器的 display 设为 flex:
css
.container {
display: flex;
} 容器成为 flex 容器,它的直接子元素成为 flex 子项。两条轴线定义了 flex 的世界:
- 主轴(main axis)——子项排列的方向
- 交叉轴(cross axis)——与主轴垂直的方向
html
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div> 容器属性
这些属性写在 flex 容器上,控制所有子项的布局行为。
flex-direction — 主轴方向
css
.container {
display: flex;
flex-direction: row; /* 默认:左→右 */
flex-direction: row-reverse; /* 右→左 */
flex-direction: column; /* 上→下 */
flex-direction: column-reverse; /* 下→上 */
} justify-content — 主轴对齐
控制子项在主轴上的分布方式:
| 值 | 效果 |
|---|---|
flex-start | 靠主轴起点(默认) |
flex-end | 靠主轴终点 |
center | 居中 |
space-between | 两端对齐,中间均匀分布 |
space-around | 每个子项两侧有相等间距 |
space-evenly | 所有间距相等(包括两端) |
css
.navbar {
display: flex;
justify-content: space-between;
}
/* Logo 在最左,导航链接在最右 */ align-items — 交叉轴对齐
控制子项在交叉轴上的对齐方式:
| 值 | 效果 |
|---|---|
stretch | 拉伸填满容器(默认) |
flex-start | 靠交叉轴起点 |
flex-end | 靠交叉轴终点 |
center | 居中 |
baseline | 文本基线对齐 |
css
/* 垂直居中(单行) */
.vertical-center {
display: flex;
align-items: center;
} flex-wrap — 换行
默认情况下 flex 子项不换行,全部挤在一行:
css
.container {
display: flex;
flex-wrap: nowrap; /* 不换行(默认) */
flex-wrap: wrap; /* 允许换行 */
flex-wrap: wrap-reverse; /* 换行,但交叉轴反向 */
} align-content — 多行对齐
当 flex-wrap: wrap 且有多行时,控制行与行之间在交叉轴上的分布:
css
.container {
display: flex;
flex-wrap: wrap;
align-content: space-between; /* 行之间均匀分布 */
} 取值与 justify-content 相同。如果只有一行,align-content 无效。
gap — 子项间距
css
.container {
display: flex;
gap: 1rem; /* 行间距和列间距相同 */
gap: 1rem 2rem; /* 行间距 列间距 */
row-gap: 1rem; /* 仅行间距 */
column-gap: 2rem; /* 仅列间距 */
} gap 是管理间距的现代方案,取代了以往用 margin + :not(:last-child) 的技巧。它只在子项之间产生间距,不会在容器边缘产生多余空白。
子项属性
这些属性写在 flex 子项上,控制各自的行为。
flex — 伸缩简写
flex 是三个属性的简写:flex-grow、flex-shrink、flex-basis:
css
.item {
flex: 1; /* flex-grow: 1; flex-shrink: 1; flex-basis: 0 */
flex: 1 0 200px; /* grow: 1; shrink: 0; basis: 200px */
flex: auto; /* 1 1 auto — 按内容比例分配 */
flex: none; /* 0 0 auto — 不伸缩,保持固有尺寸 */
} flex-grow — 放大比例
当容器有剩余空间时,子项以何种比例瓜分:
css
.item-1 { flex-grow: 1; } /* 占 1 份 */
.item-2 { flex-grow: 2; } /* 占 2 份(两倍宽) */
.item-3 { flex-grow: 0; } /* 不放大(默认) */ flex-shrink — 缩小比例
当容器空间不足时,子项以何种比例收缩:
css
.item { flex-shrink: 0; } /* 禁止收缩(保持尺寸) */ flex-basis — 初始尺寸
子项在分配剩余空间之前的初始大小:
css
.sidebar { flex-basis: 250px; } /* 初始 250px */
.content { flex: 1; } /* 占据剩余空间 */
.half { flex-basis: 50%; } align-self — 独立交叉轴对齐
覆盖容器的 align-items,对单个子项设置:
css
.special-item {
align-self: flex-start; /* 自己靠顶部,其他子项可能居中 */
} order — 排列顺序
改变子项的视觉顺序(不影响 HTML 结构):
css
.item-1 { order: 3; } /* 排在第 3 个 */
.item-2 { order: 1; } /* 排在第 1 个 */
.item-3 { order: 2; } /* 排在第 2 个 */ 默认所有子项 order: 0,从小到大排列。
order 只改变视觉顺序,不改变 DOM 结构和键盘 Tab 导航顺序。如果你的布局逻辑依赖于 order,可能意味着 HTML 结构本身需要重新审视。
经典布局模式
两栏布局(侧边栏 + 内容)
css
.layout {
display: flex;
}
.sidebar {
width: 250px;
flex-shrink: 0; /* 侧边栏不会被压缩 */
}
.content {
flex: 1; /* 占据剩余空间 */
} html
<div class="layout">
<aside class="sidebar">侧边栏</aside>
<main class="content">主要内容</main>
</div> 三栏布局(圣杯/双飞翼)
css
.three-col {
display: flex;
gap: 2rem;
}
.side-left { width: 200px; }
.content { flex: 1; }
.side-right { width: 200px; } 居中(水平+垂直)
css
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 300px;
} 导航栏(Logo 左 + 菜单右)
css
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
height: 64px;
}
.nav-menu {
display: flex;
gap: 1.5rem;
} 自适应卡片网格
css
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
flex: 1 1 300px; /* 最小 300px,空间充裕时等分 */
max-width: 400px;
} Flexbox 擅长一维布局(一行或一列)。如果你需要对行和列同时进行精确控制(如一整页的二维网格),应该使用 CSS Grid。