CSS Flex 布局精讲:从基础到实战,彻底掌握弹性布局

在 CSS 布局的发展历程中,Flex 布局(弹性布局)的出现彻底改变了传统布局的繁琐 —— 它告别了依赖floatposition的 hack 式写法,以直观的 “弹性” 思维实现元素的对齐、分布与自适应,成为现代前端开发中最常用的布局方案之一。本文将从核心概念到实战案例,带你系统掌握 Flex 布局的所有关键知识点。

一、什么是 Flex 布局?

Flex(Flexible Box,弹性盒)是 CSS3 引入的一种一维布局模型—— 它通过定义 “容器” 和 “项目” 的关系,控制项目在 “主轴” 和 “交叉轴” 上的排列方式,实现灵活的空间分配与对齐。

相比传统布局,Flex 的核心优势在于:

  • 简化对齐:轻松实现水平 / 垂直居中、两端对齐等常见需求;
  • 自适应强:自动分配剩余空间或收缩项目,适配不同屏幕尺寸;
  • 摆脱 hack:无需清除浮动、避免 margin 塌陷,逻辑更直观。

二、Flex 布局的核心概念:容器与项目

Flex 布局的所有规则都围绕 “容器” 和 “项目” 展开,先明确这两个概念是学习的前提。

1. 容器(Flex Container)

需要开启 Flex 布局的父元素,通过设置display: flexdisplay: inline-flex将其定义为 Flex 容器。

  • display: flex:容器为块级元素(独占一行,可设置宽高);
  • display: inline-flex:容器为行内块元素(宽度由内容决定,与其他行内元素同行排列)。

注意:一旦元素成为 Flex 容器,其内部的子元素(项目)将默认脱离文档流,容器的floatclearvertical-align属性会失效。

2. 项目(Flex Item)

Flex 容器的直接子元素就是 Flex 项目(间接子元素不生效)。例如:

<div class="container"> <!-- Flex容器 -->
  <div class="item">1</div> <!-- Flex项目 -->
  <div class="item">2</div> <!-- Flex项目 -->
  <div class="item">3</div> <!-- Flex项目 -->
</div>

3. 两大轴:主轴与交叉轴

Flex 布局的核心是 “轴” 的概念 —— 所有项目的排列、对齐都围绕主轴(Main Axis) 和交叉轴(Cross Axis) 展开,两轴始终垂直。

轴的类型定义方向控制
主轴项目的主要排列方向(默认水平从左到右)由容器的flex-direction属性控制
交叉轴垂直于主轴的方向(默认垂直从上到下)随主轴方向自动变化

例如:

  • 当主轴为 “水平方向” 时,交叉轴为 “垂直方向”;
  • 当主轴为 “垂直方向” 时,交叉轴为 “水平方向”。

三、Flex 容器的 6 个核心属性

Flex 容器通过 6 个属性控制项目的整体排列规则,是 Flex 布局的重点。

1. flex-direction:控制主轴方向(核心)

决定主轴的方向,直接影响项目的排列方向。

取值主轴方向项目排列效果
row(默认)水平从左到右项目从左往右排列
row-reverse水平从右到左项目从右往左排列
column垂直从上到下项目从上往下排列
column-reverse垂直从下到上项目从下往上排列

示例

<template>
  <div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  flex-direction: column; /* 主轴垂直,项目从上到下排 */
  height: 300px; /* 给容器高度,方便观察垂直排列 */
  border: 1px solid #000;
}
.item {
  width: 100px;
  height: 50px;
  background: #4285f4;
  color: white;
  margin: 5px;
}
</style>

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

默认情况下,项目会在主轴上 “挤在一起不换行”(即使超出容器宽度),flex-wrap用于控制项目溢出时是否换行。

取值效果
nowrap(默认)不换行,项目可能溢出容器
wrap换行,溢出的项目向下排列(沿交叉轴正方向)
wrap-reverse换行,溢出的项目向上排列(沿交叉轴反方向)

代码示例(容器宽度 300px,3 个项目各 100px,默认不换行时刚好排下;若项目各 120px,wrap会让第 3 个项目换行):

3. flex-flowflex-direction + flex-wrap 简写

为简化代码,flex-flowflex-directionflex-wrap的复合属性,语法:

flex-flow: <flex-direction> <flex-wrap>;

示例:

.container {
  display: flex;
  flex-flow: row wrap;
  width: 300px;
  border: 1px solid #000;
}

常用示例

  • flex-flow: row wrap;(水平排列 + 溢出换行,最常用)
  • flex-flow: column nowrap;(垂直排列 + 不换行)

4. justify-content:主轴对齐方式(高频)

控制项目在主轴上的对齐方式,是实现 “水平居中”“两端对齐” 等需求的核心属性

取值对齐效果(以主轴水平为例)
flex-start(默认)项目靠主轴起点对齐(左对齐)
flex-end项目靠主轴终点对齐(右对齐)
center项目在主轴居中对齐(水平居中)
space-between两端对齐:项目间距相等,首尾项目贴容器边缘
space-around项目两侧间距相等:项目间间距 = 项目与容器边缘间距 × 2
space-evenly所有间距相等:项目间间距 = 项目与容器边缘间距

代码示例(实现水平居中):

<template>
  <div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  width: 700px;
  justify-content: center; /* 主轴居中 */
  border: 1px solid #000;
}
.item {
  width: 120px; /* 3*120=360 > 300,会换行 */
  height: 50px;
  background: #ea4335;
  color: white;
  margin: 5px;
}
</style>

效果:

5. align-items:交叉轴对齐方式(单行项目)

控制项目在交叉轴上的对齐方式,仅作用于 “单行项目”(即flex-wrap: nowrap时)。

取值对齐效果(以交叉轴垂直为例)
stretch(默认)项目未设高度时,拉伸至与容器等高
flex-start项目靠交叉轴起点对齐(上对齐)
flex-end项目靠交叉轴终点对齐(下对齐)
center项目在交叉轴居中对齐(垂直居中)
baseline项目按文字基线对齐(而非项目本身对齐)

关键区别

  • stretch:依赖项目无固定高度(或高度为auto);
  • baseline:若项目文字大小不同,会按文字的基线(底部对齐线)排列,而非项目底部对齐。

代码示例(实现水平 + 垂直居中):

<template>
  <div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  width: 400px;
  height: 200px; /* 容器必须有高度,交叉轴对齐才可见 */
  justify-content: center; /* 主轴居中(水平) */
  align-items: center; /* 交叉轴居中(垂直) */
  border: 1px solid #000;
}
.item {
  width: 120px; /* 3*120=360 > 300,会换行 */
  height: 50px;
  background: #ea4335;
  color: white;
  margin: 5px;
}
</style>

6. align-content:交叉轴对齐方式(多行项目)

控制多行项目在交叉轴上的对齐方式,仅作用于 “换行后的多行项目”(即flex-wrap: wrapwrap-reverse时)。若项目只有一行,该属性无效。

取值对齐效果(以交叉轴垂直为例)
stretch(默认)多行项目拉伸至填满容器交叉轴高度
flex-start多行项目靠交叉轴起点对齐(上对齐)
flex-end多行项目靠交叉轴终点对齐(下对齐)
center多行项目在交叉轴居中对齐(垂直居中)
space-between多行两端对齐:行间距相等,首尾行贴容器边缘
space-around多行两侧间距相等:行间距 = 行与容器边缘间距 × 2

注意align-contentalign-items的核心区别是 “作用范围”—— 前者管 “多行整体”,后者管 “单行内的项目”。

四、Flex 项目的 6 个核心属性

项目的属性用于控制单个项目的排列规则,可覆盖容器的部分设置(如align-self覆盖align-items)。

1. order:控制项目的排列顺序

默认情况下,项目按 HTML 书写顺序排列(order: 0)。通过order可自定义顺序,数值越小,排列越靠前,支持负数。

代码示例

<template>
  <div class="container">
    <div class="item1"></div>
    <div class="item2"></div>
    <div class="item3"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
}
.item1 {
  order: 2;
  width: 100px;
  height: 100px;
  /* 红色*/
  background-color: rgb(255, 209, 209);
} /* 排第3位 */

.item2 {
  order: -1;
  width: 100px;
  height: 100px;
  /* 绿色 */
  background-color: rgb(209, 255, 227);
} /* 排第1位(负数最小) */

.item3 {
  order: 1;
  width: 100px;
  height: 100px;
  /* 紫色 */
  background-color: rgb(214, 209, 255);
} /* 排第2位 */
</style>

显示效果

2. flex-grow:控制项目的放大比例

当容器有剩余空间时,flex-grow定义项目的 “放大比例”,默认值为0(即不放大)。

  • 若所有项目的flex-grow总和为N,则每个项目分得的剩余空间比例为:自身flex-grow / N
  • 若某项目flex-grow: 0,则无论剩余空间多少,它都不放大。

代码示例(容器宽度 400px,3 个项目各 100px,剩余空间 100px):

<template>
  <div class="container">
    <div class="item item1"></div>
    <div class="item item2"></div>
    <div class="item item3"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  width: 400px;
}
.item {
  width: 100px;
  height: 50px;
}

.item1 {
  background-color: rgb(249, 210, 210);
  flex-grow: 1;
} /* 占剩余空间1/(1+2) = 1/3 ≈33px,最终宽度133px */
.item2 {
  background-color: rgb(210, 249, 216);
  flex-grow: 2;
} /* 占剩余空间2/3 ≈67px,最终宽度167px */
.item3 {
  background-color: rgb(216, 210, 249);
  flex-grow: 0;
} /* 不放大,宽度保持100px */
</style>

展示效果

3. flex-shrink:控制项目的缩小比例

当容器空间不足时,flex-shrink定义项目的 “缩小比例”,默认值为1(即允许缩小)。

  • 若所有项目的flex-shrink总和为M,则每个项目缩小的幅度比例为:(自身宽度 × 自身flex-shrink) / 所有项目(宽度×flex-shrink)总和
  • 若某项目flex-shrink: 0,则无论空间是否不足,它都不缩小(可能导致溢出)。

代码示例(容器宽度 300px,3 个项目各 120px,总宽度 360px,需缩小 60px):

<template>
  <div class="container">
    <div class="item item1"></div>
    <div class="item item2"></div>
    <div class="item item3"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  width: 300px;
}
.item {
  width: 120px;
  height: 50px;
}

.item1 {
  background-color: rgb(249, 210, 210);
  flex-shrink: 1;
} /* 缩小幅度:(120×1)/(120×1+120×2+120×0) ×60 = 20px,最终宽度100px */

.item2 {
  background-color: rgb(210, 249, 216);
  flex-shrink: 2;
} /* 缩小幅度:(120×2)/360 ×60 =40px,最终宽度80px */

.item3 {
  background-color: rgb(216, 210, 249);
  flex-shrink: 0;
} /* 不缩小,宽度保持120px */
</style>

展示效果

4. flex-basis:控制项目的初始尺寸

定义项目在主轴上的 “初始尺寸”,默认值为auto(即项目自身的尺寸,如widthheight)。

  • 若主轴为水平方向(row),flex-basis优先级高于width(设置flex-basis后,width失效);
  • 若主轴为垂直方向(column),flex-basis优先级高于height
  • 可设置具体数值(如200px50%),也可设auto0

代码示例

.container { display: flex; }
.item {
  flex-basis: 150px; /* 主轴水平,初始宽度150px,width会失效 */
  width: 100px; /* 无效,被flex-basis覆盖 */
  height: 50px;
}

5. flexflex-grow + flex-shrink + flex-basis 简写

为简化代码,flex是三者的复合属性,语法:

flex: <flex-grow> <flex-shrink> <flex-basis>;

常用简写场景(必须牢记):

简写形式等价完整写法适用场景
flex: 1flex: 1 1 0%项目平均分配剩余空间(如等分导航栏)
flex: autoflex: 1 1 auto项目先按自身尺寸排列,再分配剩余空间
flex: noneflex: 0 0 auto项目不放大、不缩小,按自身尺寸排列(固定尺寸)
flex: 0 1 auto(默认值)项目不放大、允许缩小,按自身尺寸排列

实战建议:实际开发中几乎不用单独写flex-grow/flex-shrink/flex-basis,而是直接用flex简写。

6. align-self:单个项目的交叉轴对齐

控制单个项目在交叉轴上的对齐方式,可覆盖容器的align-items属性,默认值为auto(即继承容器的align-items)。

取值与align-items完全一致:autostretchflex-startflex-endcenterbaseline

代码示例(大部分项目垂直居中,单个项目靠下):

<template>
  <div class="container">
    <div class="item item1"></div>
    <div class="item item2"></div>
    <div class="item item3"></div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  height: 200px;
  align-items: center; /* 容器默认垂直居中 */
  border: 1px solid #000;
}
.item {
  width: 100px;
  height: 50px;
  background: #fbbc05;
}
.item2 {
  align-self: flex-end;
} /* 单个项目靠下对齐,覆盖容器的align-items */
</style>

展示效果

五、Flex 布局实战案例

掌握属性后,通过实战案例巩固应用,以下是 3 个高频场景。

案例 1:水平垂直居中(最经典)

传统布局实现垂直居中需要复杂的 hack(如position + transform),Flex 只需 2 行代码:

<template>
  <div class="container">
    <div class="box">我是水平垂直居中的内容</div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.container {
  display: flex;
  width: 500px;
  height: 300px;
  background: #e8eaed;
  /* 核心代码 */
  justify-content: center; /* 主轴居中(水平) */
  align-items: center; /* 交叉轴居中(垂直) */
}
.box {
  width: 200px;
  height: 100px;
  background: #4285f4;
  color: white;
  text-align: center;
  line-height: 100px;
}
</style>

案例 2:自适应导航栏(左 Logo + 右菜单)

需求:Logo 居左,菜单居右,导航栏自适应宽度。

<template>
  <nav class="navbar">
    <div class="logo">MyLogo</div>
    <ul class="menu">
      <li>首页</li>
      <li>关于</li>
      <li>联系</li>
    </ul>
  </nav>
</template>
<script setup lang="ts"></script>
<style>
.navbar {
  display: flex;
  justify-content: space-between; /* 主轴两端对齐,Logo左、菜单右 */
  align-items: center; /* 垂直居中 */
  padding: 0 20px;
  height: 60px;
  background: #202124;
  color: white;
}
.logo {
  font-size: 20px;
  font-weight: bold;
}
.menu {
  display: flex; /* 菜单内部横向排列 */
  list-style: none;
  gap: 20px; /* 菜单项间距(替代margin) */
}
</style>

案例 3:自适应卡片布局(响应式)

需求:卡片一行最多排 3 个,屏幕变小时自动换行,且卡片间距均匀

<template>
  <div class="card-container">
    <div class="card">卡片1</div>
    <div class="card">卡片2</div>
    <div class="card">卡片3</div>
    <div class="card">卡片4</div>
    <div class="card">卡片5</div>
  </div>
</template>
<script setup lang="ts"></script>
<style>
.card-container {
  display: flex;
  flex-wrap: wrap; /* 溢出换行 */
  gap: 20px; /* 卡片间距(行+列) */
  padding: 20px;
  background: #f5f5f5;
}
.card {
  flex: 1 1 calc(33.333% - 20px); /* 核心:1/3宽度,减去gap的影响 */
  min-width: 250px; /* 最小宽度,屏幕过小时不再缩小 */
  height: 200px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 18px;
}
</style>

  • calc(33.333% - 20px):确保卡片宽度为 1/3 容器宽度,同时减去gap的间距,避免换行异常;
  • min-width: 250px:当屏幕宽度过小时(如手机),卡片不再缩小,而是自动换行,实现响应式。

六、常见误区与注意事项

  1. 容器的float/clear失效:Flex 容器的floatclear属性不生效,若需容器水平居中,直接给容器设置margin: 0 auto即可。
  2. flex-basiswidth的优先级:主轴为row时,flex-basis优先级高于width;若flex-basis: auto,则width生效。
  3. align-content仅作用于多行:若项目未换行(flex-wrap: nowrap),align-content无效,需用align-items
  4. 项目的margin: auto可强制对齐:若给项目设置margin-left: auto,项目会被推到主轴右侧(类似flex-end),可用于实现 “左 Logo + 右菜单” 的简化版。

七、总结

Flex 布局是现代前端布局的 “瑞士军刀”,其核心是通过 “容器 - 项目” 和 “主轴 - 交叉轴” 的模型,实现灵活的对齐与空间分配。掌握以下关键点,即可应对 90% 以上的布局需求:

  1. 容器属性:flex-direction(主轴方向)、justify-content(主轴对齐)、align-items(单行交叉轴对齐);
  2. 项目属性:flex(简写,控制放大缩小)、align-self(单个项目交叉轴对齐);
  3. 实战技巧:flex: 1等分空间、justify-content + align-items居中、flex-wrap + gap自适应换行。

通过多练习实际案例(如导航栏、卡片列表、表单布局),即可彻底熟练 Flex 布局,告别传统布局的繁琐与 hack。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值