先想象一个场景
你去奶茶店排队买东西。如果只有你一个人,队伍很短;如果突然来了一群人,队伍会自动拉长——但每个人之间的间距、队形排列方式,都是可以”设置”的。
Flexbox 就是 CSS 里的这种排队机制。记住 Flex 的核心:它专门解决一行或一列的元素如何排列、对齐、分配空间的问题,这就是所谓的一维布局。
Flex 容器与 Flex Item
想让一堆元素变成”排队”模式,只需要给父元素加一个 display: flex。这个父元素就变成了 flex 容器,它的直接子元素自动成为 flex item。
<!-- CSS 原生写法 -->
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container {
display: flex;
}
</style>
<!-- Tailwind 写法 -->
<div class="flex">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
主轴与交叉轴
Flex 有两条轴:主轴(main axis)和交叉轴(cross axis)。
- 主轴:默认是水平方向(从左到右)
- 交叉轴:垂直于主轴的方向
| 属性 | CSS | Tailwind | 说明 |
|---|---|---|---|
| 主轴水平(默认) | flex-direction: row | flex-row | 元素从左往右排 |
| 主轴垂直 | flex-direction: column | flex-col | 元素从上往下排 |
justify-content:主轴对齐
控制元素在主轴上的排列方式,相当于”队伍怎么站队”。
| CSS 属性 | Tailwind | 效果 |
|---|---|---|
flex-start | justify-start | 靠起点对齐 |
center | justify-center | 居中对齐 |
flex-end | justify-end | 靠终点对齐 |
space-between | justify-between | 两端对齐,中间均匀分布 |
space-around | justify-around | 每个元素周围间距相等 |
space-evenly | justify-evenly | 元素之间和两端间距完全相等 |
<!-- Tailwind 示例:水平居中 -->
<div class="flex justify-center gap-4">
<div class="h-16 w-16 rounded bg-red-200">A</div>
<div class="h-16 w-16 rounded bg-blue-200">B</div>
<div class="h-16 w-16 rounded bg-green-200">C</div>
</div>
align-items:交叉轴对齐
控制元素在交叉轴上的对齐方式,相当于”每个人在队伍里站多高”。
| CSS 属性 | Tailwind | 效果 |
|---|---|---|
flex-start | items-start | 靠交叉轴起点对齐 |
center | items-center | 居中对齐 |
flex-end | items-end | 靠交叉轴终点对齐 |
stretch | items-stretch | 拉伸填满容器(默认) |
baseline | items-baseline | 按文字基线对齐 |
<!-- Tailwind 示例:垂直居中 -->
<div class="flex h-40 items-center justify-center bg-gray-100">
<div class="h-16 w-16 rounded bg-red-200">A</div>
<div class="h-16 w-16 rounded bg-blue-200">B</div>
<div class="h-16 w-16 rounded bg-green-200">C</div>
</div>
重点:水平垂直同时居中
这是 Flex 最常用的场景——让一个元素在容器里完全居中。
<!-- Tailwind 写法 -->
<div class="flex h-screen items-center justify-center bg-gray-100">
<div
class="flex h-32 w-32 items-center justify-center rounded-lg bg-blue-400 shadow-lg"
>
<span class="font-bold text-white">居中内容</span>
</div>
</div>
/* 对应的 CSS 原生写法 */
.container {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
flex-wrap:换行控制
默认情况下,所有 flex item 会挤在一行里。如果子元素太多,flex-wrap: wrap 可以让它们换行。
| CSS 属性 | Tailwind | 说明 |
|---|---|---|
nowrap | flex-nowrap | 不换行(默认),子元素会被压缩 |
wrap | flex-wrap | 放不下时自动换行 |
wrap-reverse | flex-wrap-reverse | 换行但顺序反转 |
<!-- Tailwind 示例:自动换行卡片 -->
<div class="flex flex-wrap gap-4 p-4">
<div class="flex h-32 w-32 items-center justify-center rounded bg-red-200">
卡片1
</div>
<div class="flex h-32 w-32 items-center justify-center rounded bg-blue-200">
卡片2
</div>
<div class="flex h-32 w-32 items-center justify-center rounded bg-green-200">
卡片3
</div>
<div class="flex h-32 w-32 items-center justify-center rounded bg-yellow-200">
卡片4
</div>
<div class="flex h-32 w-32 items-center justify-center rounded bg-purple-200">
卡片5
</div>
</div>
gap:间距
控制 flex item 之间的间距。注意 gap 只作用于 item 与 item 之间,不会作用于容器边缘。
| CSS 属性 | Tailwind | 说明 |
|---|---|---|
gap: 8px | gap-2 | 行列间距相同 |
gap: 16px | gap-4 | 间距稍大 |
row-gap: 8px | gap-y-2 | 仅行间距 |
column-gap: 8px | gap-x-2 | 仅列间距 |
<div class="flex gap-4">
<div class="bg-red-200 p-4">A</div>
<div class="bg-blue-200 p-4">B</div>
<div class="bg-green-200 p-4">C</div>
</div>
flex-grow / flex-shrink / flex-basis
这三个属性控制 flex item 如何分配剩余空间,以及空间不足时如何收缩。
| 属性 | 说明 | CSS 示例 | Tailwind |
|---|---|---|---|
flex-grow | 增长比例,默认 0(不增长) | flex-grow: 1 | grow |
flex-shrink | 收缩比例,默认 1(可收缩) | flex-shrink: 0 | shrink-0 |
flex-basis | 初始大小 | flex-basis: 200px | basis-[200px] |
简写形式 flex:
| Tailwind | 等价 CSS |
|---|---|
flex-1 | flex: 1 1 0%(可增长可收缩) |
flex-auto | flex: 1 1 auto |
flex-none | flex: 0 0 auto(不增长不收缩) |
<!-- Tailwind 示例:三个元素,第二个占更多空间 -->
<div class="flex gap-4">
<div class="shrink-0 basis-32 bg-red-200 p-4">固定宽度</div>
<div class="flex-1 bg-blue-200 p-4">占满剩余空间</div>
<div class="shrink-0 basis-32 bg-green-200 p-4">固定宽度</div>
</div>
实战:导航栏
<!-- Tailwind:经典导航栏布局 -->
<nav class="flex items-center justify-between bg-white px-6 py-4 shadow">
<div class="text-xl font-bold">Logo</div>
<div class="flex gap-6">
<a href="#" class="text-gray-600 hover:text-gray-900">首页</a>
<a href="#" class="text-gray-600 hover:text-gray-900">文章</a>
<a href="#" class="text-gray-600 hover:text-gray-900">关于</a>
</div>
<button class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600">
登录
</button>
</nav>
/* 对应 CSS 原生写法 */
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
background: white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
nav a {
color: #4b5563;
text-decoration: none;
margin: 0 1rem;
}
nav a:hover {
color: #111827;
}
常见踩坑与避坑指南
踩坑 1:子元素被压缩
Flex 默认 flex-shrink: 1,当容器空间不够时,子元素会被压缩。如果你不希望某个元素被压缩,设置 flex-shrink: 0。
<!-- 这个元素永远不会被压缩 -->
<div class="w-32 shrink-0 bg-red-200">固定宽度</div>
踩坑 2:align-items 默认 stretch
Flex 默认会把所有子元素拉伸到与容器等高。如果你不想这样,显式设置 align-items。
<!-- 让元素保持自身高度,不拉伸 -->
<div class="flex items-start gap-4">
<div class="bg-red-200 pt-4">自身高度</div>
<div class="bg-blue-200">会被拉伸</div>
</div>
踩坑 3:justify-content 与 gap 的距离计算
justify-content: space-between 时,元素之间的实际距离 = gap + 元素之间自动计算的间距。记住 gap 是额外增加的间距,不是元素之间的距离。
踩坑 4:flex-basis 和 width 的优先级
flex-basis 优先级高于 width。如果同时设置了 width: 200px 和 flex-basis: 100px,实际宽度是 100px。
速查表
| 功能 | CSS 原生 | Tailwind |
|---|---|---|
| 启用 flex | display: flex | flex |
| 主轴方向 | flex-direction: row/column | flex-row / flex-col |
| 主轴对齐 | justify-content: ... | justify-start / center / end / between / around / evenly |
| 交叉轴对齐 | align-items: ... | items-start / center / end / stretch / baseline |
| 换行 | flex-wrap: wrap | flex-wrap |
| 间距 | gap: 16px | gap-4 |
| 占据剩余空间 | flex: 1 | flex-1 |
| 固定宽度 | flex-shrink: 0 | shrink-0 |
| 禁止换行 | flex-wrap: nowrap | flex-nowrap |
记住 Flex 的核心:Flex 是一维布局工具,适合处理一行或一列的元素排列。当你的布局需要同时控制行和列时,就需要 Grid 了——这就是我们下一篇要讲的内容。