Flex 布局实战指南:从踩坑到精通,解决 90% 布局难题

Flex 布局实战指南:从踩坑到精通,解决 90% 布局难题

前言:你是否也被这些 Flex 问题折磨过?

"为什么我用justify-content: center却无法垂直居中?"

"align-itemsalign-content到底什么时候生效?"

"设置了width: 200px,加了flex:1后怎么没用了?"

作为前端开发最常用的布局方案,Flex(弹性布局)以 "灵活" 著称,但这份灵活也让很多开发者陷入 "混乱"------ 核心原因是没吃透 "主轴与交叉轴" 的逻辑,以及各属性的适用场景。本文将从基础概念到实战案例,带你彻底搞懂 Flex 布局,从此告别 "试错式调样式"。

一、Flex 布局基础:先搞懂这两个核心概念

在学习任何属性前,必须先理清 Flex 布局的 "骨架"------父元素(flex container)子元素(flex item) 的关系,以及最关键的主轴与交叉轴

1.1 什么是 Flex 布局?

Flex(Flexible Box)即 "弹性布局",通过给父元素设置display: flex,让其所有子元素自动成为 "弹性子元素",从而实现灵活的排列、对齐和尺寸分配。

一句话总结:父元素控制 "整体排列规则",子元素控制 "自身特殊表现"。

css 复制代码
/\* 最简单的Flex布局示例 \*/

.parent {

        display: flex; /\* 父元素开启Flex布局 \*/

        width: 500px;

        height: 300px;

        background: #f5f5f5;

}

.child {

        width: 100px;

        height: 100px;

        background: #42b983;

        margin: 10px;

}

效果:3 个child会自动沿水平方向排列(默认主轴方向),无需浮动或定位。

1.2 主轴与交叉轴:Flex 布局的 "坐标系"

这是最容易混淆的点!记住:所有 Flex 属性都基于 "主轴" 和 "交叉轴",而非固定的 "水平 / 垂直方向"

  • 主轴(main axis) :子元素的排列方向,由flex-direction决定(默认水平向左)。

  • 交叉轴(cross axis):与主轴垂直的方向(默认垂直向下)。

举个例子:当flex-direction: column(主轴设为垂直)时,原来的 "水平轴" 变成交叉轴,"垂直轴" 变成主轴 ------ 此时justify-content(主轴对齐)控制垂直方向,align-items(交叉轴对齐)控制水平方向,这也是很多人 "垂直居中失效" 的根源!

核心口诀 :先看flex-direction定主轴,再用对应属性调对齐。

二、父元素的 6 个核心属性:控制整体布局

父元素的属性决定了子元素的 "排列规则",6 个属性覆盖 "方向、换行、对齐" 三大需求,每个属性都有明确的适用场景。

2.1 flex-direction:决定主轴方向(子元素排列方向)

作用:定义主轴的方向,直接影响子元素的排列方向。

取值与效果

取值 主轴方向 子元素排列效果 适用场景
row(默认) 水平向左 从左到右排列 导航栏、水平列表
row-reverse 水平向右 从右到左排列 反向导航、特殊排版
column 垂直向上 从上到下排列 表单、垂直列表、卡片组
column-reverse 垂直向下 从下到上排列 特殊垂直布局(极少用)

代码演示(row vs column)

css 复制代码
/\* 1. 水平排列(row):导航栏场景 \*/

.nav {

        display: flex;

        flex-direction: row; /\* 默认,可省略 \*/

        justify-content: space-between; /\* 两端对齐 \*/

        padding: 0 20px;

        background: #fff;

}

.nav-item {

        padding: 10px;

}

/\* 2. 垂直排列(column):表单场景 \*/

.form {

        display: flex;

        flex-direction: column;

        gap: 15px; /\* 子元素间距,Flex布局常用 \*/

        width: 300px;

}

.form-item {

        display: flex;

        flex-direction: row; /\* 子元素内部水平排列 \*/

        gap: 10px;

}

一句话总结 :水平布局用row,垂直布局用column,别搞反主轴方向!

2.2 flex-wrap:控制子元素是否换行

作用:当子元素总宽度 / 高度超过父元素时,是否换行(默认不换行,会压缩子元素)。

取值与效果

取值 效果 适用场景
nowrap(默认) 不换行,子元素会被压缩 导航栏(不允许换行)
wrap 换行,第一行在上 卡片网格、商品列表
wrap-reverse 换行,第一行在下 特殊排版(极少用)

常见误区 :做卡片布局时,忘记加flex-wrap: wrap,导致卡片被压缩变形!

代码演示(卡片网格)

css 复制代码
.card-container {

        display: flex;

        flex-direction: row;

        flex-wrap: wrap; /\* 关键:超出换行 \*/

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

}

.card {

        width: 200px; /\* 固定宽度 \*/

        height: 300px;

        background: #fff;

        border-radius: 8px;

}

效果:当父元素宽度不足时,卡片自动换行,保持原有尺寸。

2.3 flex-flow:flex-direction + flex-wrap 的简写

作用 :简化代码,将 "方向" 和 "换行" 合并设置,默认值row nowrap

语法flex-flow: <flex-direction> || <flex-wrap>

示例

css 复制代码
/\* 等价于 flex-direction: row; flex-wrap: wrap; \*/

.card-container {

        display: flex;

        flex-flow: row wrap;

        gap: 20px;

}

2.4 justify-content:主轴上的对齐方式

作用 :控制子元素在主轴方向 上的对齐方式(水平或垂直,取决于flex-direction)。

取值与效果(以主轴为水平为例)

取值 效果 适用场景
flex-start(默认) 靠主轴起点对齐(左对齐) 普通列表
flex-end 靠主轴终点对齐(右对齐) 右侧操作栏
center 主轴居中对齐 水平居中(如标题)
space-between 两端对齐,子元素间距相等 导航栏(两端 logo + 菜单)
space-around 子元素两侧间距相等(中间间距是边缘 2 倍) 均匀分布的卡片

代码演示(space-between 导航栏)

css 复制代码
.nav {

        display: flex;

        flex-flow: row nowrap;

        justify-content: space-between; /\* 两端对齐 \*/

        align-items: center; /\* 交叉轴居中(垂直居中) \*/

        height: 60px;

        padding: 0 20px;

        background: #fff;

}

.nav-logo {

        width: 100px;

}

.nav-menu {

        display: flex;

        gap: 20px;

}

效果:logo 在左,菜单在右,垂直居中对齐。

2.5 align-items:交叉轴上的单行对齐

作用 :控制子元素在交叉轴方向 上的对齐方式,仅对 "单行子元素" 生效(多行用align-content)。

取值与效果(以交叉轴为垂直为例)

取值 效果 适用场景
stretch(默认) 子元素高度占满父元素(需子元素无固定高度) 卡片等高布局
flex-start 靠交叉轴起点对齐(上对齐) 顶部对齐的列表
flex-end 靠交叉轴终点对齐(下对齐) 底部对齐的操作栏
center 交叉轴居中对齐(垂直居中) 水平垂直居中(如弹窗)
baseline 按子元素文字基线对齐 文字与图标对齐

常见场景:水平垂直居中(面试高频):

css 复制代码
/\* 父元素:主轴水平,交叉轴垂直 \*/

.container {

        display: flex;

        justify-content: center; /\* 主轴(水平)居中 \*/

        align-items: center; /\* 交叉轴(垂直)居中 \*/

        width: 500px;

        height: 300px;

        background: #f5f5f5;

}

.child {

        width: 100px;

        height: 100px;

        background: #42b983;

}

效果:childcontainer中完全居中,无需定位!

2.6 align-content:交叉轴上的多行对齐

作用 :控制 "多行子元素" 在交叉轴上的对齐方式,单行子元素时无效 (这是与align-items的核心区别)。

取值与效果(以交叉轴为垂直为例)

取值 效果 适用场景
stretch(默认) 多行高度占满父元素 多行卡片等高
flex-start 靠交叉轴起点对齐(上对齐) 多行列表顶部对齐
flex-end 靠交叉轴终点对齐(下对齐) 多行列表底部对齐
center 交叉轴居中对齐 多行内容整体居中
space-between 两端对齐,行间距相等 均匀分布的多行卡片
space-around 每行两侧间距相等 宽松的多行布局

代码演示(space-between 多行卡片)

css 复制代码
.card-container {

        display: flex;

        flex-flow: row wrap;

        align-content: space-between; /\* 多行垂直两端对齐 \*/

        width: 640px;

        height: 600px; /\* 父元素固定高度,才有多行对齐效果 \*/

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

}

.card {

        width: 200px;

        height: 250px;

        background: #fff;

}

效果:两行卡片分别靠顶部和底部对齐,中间间距自动分配。

align-items vs align-content 区别

  • align-items:作用于 "单个子元素",控制每行子元素的对齐;

  • align-content:作用于 "所有行",控制多行整体的对齐(单行无效)。

三、子元素的 6 个核心属性:控制自身表现

子元素的属性用于 "个性化调整",比如改变排列顺序、控制放大缩小、单独对齐,解决 "特殊子元素" 的需求。

3.1 order:改变子元素的排列顺序

作用:通过数值控制子元素的排列优先级,数值越小越靠前(默认 0)。

特点:无需修改 HTML 结构,仅通过 CSS 调整顺序,适合动态布局。

代码演示(置顶通知)

css 复制代码
.list {

        display: flex;

        flex-direction: column;

        gap: 10px;

        padding: 20px;

}

.list-item {

        padding: 10px;

        background: #fff;

}

/\* 通知项置顶(order=-1,比默认0小) \*/

.notice {

        order: -1;

        background: #fff3cd;

        border: 1px solid #ffeeba;

}

效果:notice项会排在所有默认list-item前面。

3.2 flex-grow:控制子元素的放大比例

作用:当父元素有 "剩余空间" 时,子元素的放大比例(默认 0,即不放大)。

规则

  • 所有子元素的flex-grow总和为 1 时,按比例分配剩余空间;

  • 若一个子元素flex-grow:2,其他为 1,則它占的剩余空间是其他的 2 倍。

代码演示(三栏布局:中间自适应)

css 复制代码
.layout {

        display: flex;

        width: 100%;

        height: 500px;

        gap: 20px;

}

/\* 左右栏固定宽度,不放大 \*/

.sidebar-left, .sidebar-right {

        width: 200px;

        flex-grow: 0; /\* 默认0,可省略 \*/

        background: #fff;

}

/\* 中间栏自适应放大(占满剩余空间) \*/

.main {

        flex-grow: 1; /\* 剩余空间全给中间 \*/

        background: #fff;

}

效果:左右栏固定 200px,中间栏随父元素宽度变化自适应。

3.3 flex-shrink:控制子元素的缩小比例

作用:当父元素 "空间不足" 时,子元素的缩小比例(默认 1,即会缩小)。

规则

  • flex-shrink:0:子元素不缩小,会保持原尺寸(可能溢出父元素);

  • 所有子元素flex-shrink:1:空间不足时等比例缩小。

常见场景(不缩小的图片)

css 复制代码
.card {

        display: flex;

        gap: 10px;

        padding: 10px;

        background: #fff;

        width: 300px; /\* 父元素固定宽度 \*/

}

/\* 图片不缩小(flex-shrink:0) \*/

.card-img {

        width: 100px;

        height: 100px;

        flex-shrink: 0; /\* 关键:防止图片被压缩变形 \*/

        object-fit: cover;

}

.card-content {

        flex-grow: 1; /\* 内容区放大,占满剩余空间 \*/

        overflow: hidden; /\* 内容溢出时隐藏 \*/

}

效果:即使父元素宽度不足,图片仍保持 100px,内容区会压缩文字(或滚动)。

3.4 flex-basis:定义子元素的基准尺寸

作用:在分配剩余空间前,子元素在主轴上的 "基准尺寸"(默认 auto,即子元素原尺寸)。

与 width/height 的区别

  • flex-basis优先级高于width/height(当主轴为水平时,flex-basis替代width);

  • flex-basis: 0%,则子元素的基准尺寸为 0,放大时忽略原宽度;

  • flex-basis: auto,则子元素的基准尺寸为原宽度,放大时保留原宽度。

代码演示(flex-basis: 0% vs auto)

css 复制代码
.parent {

        display: flex;

        width: 500px;

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

/\* flex-basis: 0%,忽略width,按比例放大 \*/

.item-0 {

        width: 100px;

        flex-basis: 0%;

        flex-grow: 1;

        background: #42b983;

}

/\* flex-basis: auto,保留width,再分配剩余空间 \*/

.item-auto {

        width: 100px;

        flex-basis: auto;

        flex-grow: 1;

        background: #ff4757;

}

效果:

  • item-0:最终宽度 = 剩余空间 / 2(忽略 100px);

  • item-auto:最终宽度 = 100px + 剩余空间 / 2(保留 100px)。

3.5 flex:flex-grow + flex-shrink + flex-basis 的简写

作用 :简化代码,是子元素最常用的属性,默认值0 1 auto

常用快捷值及含义

快捷值 等价于 效果 适用场景
flex: 0 flex: 0 1 0% 不放大,可缩小,基准尺寸 0 固定尺寸元素(如图标)
flex: 1 flex: 1 1 0% 放大,可缩小,基准尺寸 0 自适应元素(如中间栏)
flex: auto flex: 1 1 auto 放大,可缩小,基准尺寸 auto 保留原尺寸的自适应元素
flex: none flex: 0 0 auto 不放大,不缩小,基准尺寸 auto 完全固定尺寸元素

核心区别:flex:1 vs flex:auto(面试高频):

  • flex:1flex-basis:0%,忽略子元素原宽度,按比例分配剩余空间;

  • flex:autoflex-basis:auto,保留子元素原宽度,再分配剩余空间。

代码演示(区别对比)

css 复制代码
.parent {

        display: flex;

        width: 500px;

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

/\* flex:1 忽略width \*/

.item-1 {

        width: 200px;

        flex: 1;

        background: #42b983;

}

/\* flex:auto 保留width \*/

.item-auto {

        width: 200px;

        flex: auto;

        background: #ff4757;

}

效果:

  • item-1:最终宽度 = (500 - 10)/2 = 245px(忽略 200px);

  • item-auto:最终宽度 = 200px + (500 - 200*2 -10)/2 = 245px?不,实际是:父元素总宽度 500,减去 gap10,剩余 490;item-auto基准 200,item-1基准 0,总基准 200;剩余空间 490-200=290;flex-grow都是 1,各分 145;所以item-auto最终 200+145=345,item-10+145=145。

    (注:实际计算需考虑 gap,这里重点是 "flex:1 忽略 width,flex:auto 保留 width")

3.6 align-self:单独设置子元素的交叉轴对齐

作用 :覆盖父元素的align-items属性,为单个子元素设置特殊的交叉轴对齐方式(默认 auto,即继承父元素)。

取值 :与align-items一致(flex-start、flex-end、center、baseline、stretch)。

代码演示(特殊对齐的按钮)

css 复制代码
.form {

        display: flex;

        flex-direction: row;

        align-items: center; /\* 父元素默认居中对齐 \*/

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

.form-input {

        flex-grow: 1;

        padding: 8px;

        border: 1px solid #ddd;

}

/\* 按钮单独向下对齐(覆盖父元素的center) \*/

.form-btn {

        padding: 8px 16px;

        background: #42b983;

        color: #fff;

        border: none;

        align-self: flex-end;

}

效果:输入框垂直居中,按钮靠底部对齐,满足特殊布局需求。

四、Flex 布局避坑指南:解决 90% 常见错误

掌握属性后,仍可能踩坑,这 3 个误区最容易犯,一定要避开!

4.1 误区 1:主轴方向设为 column 后,对齐属性用反

错误场景 :父元素flex-direction: column(主轴垂直),想让子元素水平居中,却用了justify-content: center(主轴对齐,此时控制垂直方向),导致没效果。

正确做法 :主轴垂直时,justify-content控制垂直方向,align-items控制水平方向。

css 复制代码
/\* 错误:想水平居中,却用了justify-content \*/

.parent {

        display: flex;

        flex-direction: column;

        justify-content: center; /\* 此时控制垂直居中,不是水平 \*/

}

/\* 正确:水平居中用align-items \*/

.parent {

        display: flex;

        flex-direction: column;

        align-items: center; /\* 水平居中 \*/

        justify-content: center; /\* 垂直居中(可选) \*/

}

4.2 误区 2:用 align-content 控制单行子元素

错误场景 :子元素只有一行,却用align-content: center想让子元素垂直居中,结果没效果。

原因align-content仅对多行子元素生效,单行需用align-items

正确做法

css 复制代码
/\* 错误:单行用align-content \*/

.parent {

        display: flex;

        align-content: center; /\* 单行无效 \*/

}

/\* 正确:单行用align-items \*/

.parent {

        display: flex;

        align-items: center; /\* 单行垂直居中 \*/

}

4.3 误区 3:flex-shrink:0 导致子元素溢出

错误场景 :子元素设置flex-shrink:0(不缩小),且宽度固定,当父元素宽度不足时,子元素溢出父元素。

解决方法 :配合min-width: 0overflow: hidden,让子元素内容可压缩或滚动。

css 复制代码
/\* 错误:子元素溢出 \*/

.parent {

        display: flex;

        width: 200px; /\* 父元素宽度不足 \*/

}

.child {

        width: 300px;

        flex-shrink: 0; /\* 不缩小,导致溢出 \*/

}

/\* 正确:内容溢出时滚动 \*/

.child {

        width: 300px;

        flex-shrink: 0;

        overflow-x: auto; /\* 横向滚动 \*/

}

五、Flex 布局实战案例:从理论到应用

结合实际需求,用 Flex 实现 4 种常见布局,巩固所学知识。

5.1 案例 1:水平垂直居中(弹窗内容区)

css 复制代码
.modal {

        position: fixed;

        top: 0;

        left: 0;

        width: 100%;

        height: 100%;

        background: rgba(0,0,0,0.5);

        /\* 父元素:水平垂直居中 \*/

        display: flex;

        justify-content: center;

        align-items: center;

}

.modal-content {

        width: 500px;

        padding: 30px;

        background: #fff;

        border-radius: 8px;

}

5.2 案例 2:三栏布局(后台管理系统)

css 复制代码
.admin-layout {

        display: flex;

        width: 100%;

        height: 100vh;

}

/\* 左侧边栏:固定宽度,不放大 \*/

.sidebar {

        width: 240px;

        flex-shrink: 0;

        background: #2c3e50;

        color: #fff;

}

/\* 中间内容区:自适应放大 \*/

.content {

        flex-grow: 1;

        padding: 20px;

        background: #ecf0f1;

        overflow-y: auto;

}

/\* 右侧工具栏:固定宽度,不放大 \*/

.toolbar {

        width: 200px;

        flex-shrink: 0;

        background: #fff;

        padding: 20px;

}

5.3 案例 3:卡片网格(商品列表)

css 复制代码
.product-list {

        display: flex;

        flex-flow: row wrap;

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

        /\* 让卡片在父元素缩小时,自动调整数量 \*/

        justify-content: flex-start;

        align-content: flex-start;

}

.product-card {

        width: calc((100% - 40px) / 3); /\* 一行3个,减去2个gap \*/

        flex-shrink: 0; /\* 不缩小,保持宽度 \*/

        height: 300px;

        background: #fff;

        border-radius: 8px;

        overflow: hidden;

}

/\* 响应式:屏幕小于768px时,一行2个 \*/

@media (max-width: 768px) {

        .product-card {

          width: calc((100% - 20px) / 2);

        }

}

5.4 案例 4:导航栏(两端对齐 + 溢出滚动)

css 复制代码
.nav {

        display: flex;

        flex-flow: row nowrap;

        justify-content: space-between;

        align-items: center;

        height: 60px;

        padding: 0 20px;

        background: #fff;

        border-bottom: 1px solid #eee;

}

/\* 左侧logo:固定宽度 \*/

.nav-logo {

        width: 120px;

        flex-shrink: 0;

}

/\* 中间菜单:溢出时滚动 \*/

.nav-menu {

        display: flex;

        gap: 20px;

        margin: 0 20px;

        overflow-x: auto;

        /\* 隐藏滚动条,保留滚动功能 \*/

        scrollbar-width: none;

        -ms-overflow-style: none;

}

.nav-menu::-webkit-scrollbar {

        display: none;

}

.nav-menu-item {

        padding: 10px 0;

        white-space: nowrap; /\* 不换行 \*/

}

/\* 右侧用户区:固定宽度 \*/

.nav-user {

        width: 100px;

        flex-shrink: 0;

        text-align: right;

}

六、Flex 属性速查表(收藏备用)

父元素属性速查表

属性名 作用 取值 常用场景
flex-direction 决定主轴方向(子元素排列方向) row/row-reverse/column/column-reverse 水平 / 垂直布局
flex-wrap 控制子元素是否换行 nowrap/wrap/wrap-reverse 卡片网格、列表
flex-flow 简写(direction+wrap)
justify-content 主轴对齐方式 flex-start/flex-end/center/space-between/space-around 水平 / 垂直居中、两端对齐
align-items 交叉轴单行对齐 stretch/flex-start/flex-end/center/baseline 垂直居中、等高布局
align-content 交叉轴多行对齐 stretch/flex-start/flex-end/center/space-between/space-around 多行卡片对齐

子元素属性速查表

属性名 作用 取值 常用场景
order 改变排列顺序 (默认 0) 置顶 / 置底元素
flex-grow 放大比例 (默认 0) 自适应元素(中间栏)
flex-shrink 缩小比例 (默认 1) 固定尺寸元素(图片)
flex-basis 基准尺寸 /auto(默认 auto) 自定义基准尺寸
flex 简写(grow+shrink+basis) 0/1/auto/none 自适应、固定尺寸元素
align-self 单独交叉轴对齐 auto/flex-start/flex-end/center/baseline/stretch 特殊对齐元素

结语:Flex 布局的核心思想

Flex 布局的本质是 "弹性"------ 通过主轴与交叉轴的灵活定义,实现 "按需分配空间" 和 "精准对齐"。掌握它的关键不是死记属性,而是:

  1. 先确定主轴方向(flex-direction);

  2. 再用父元素属性控制整体布局;

  3. 最后用子元素属性调整特殊需求。

多动手实现几个实战案例,遇到问题查速查表,很快就能熟练掌握。Flex 布局是前端开发的 "瑞士军刀",用好它,能大幅提升布局效率,告别 "浮动塌陷" 和 "定位混乱" 的烦恼!总而言之,一键点赞、评论、喜欢收藏吧!这对我很重要!

相关推荐
西洼工作室1 小时前
CSS高效开发三大方向
前端·css
昔人'1 小时前
css`font-variant-numeric: tabular-nums` 用来控制数字的样式。
前端·css
不叫猫先生9 小时前
中秋连连看小游戏开发完整教程
javascript·css·小游戏·连连看
西洼工作室1 天前
SSE与轮询技术实时对比演示
前端·javascript·css
Dontla2 天前
Tailwind CSS介绍(现代CSS框架,与传统CSS框架Bootstrap对比)Tailwind介绍
前端·css·bootstrap
向上的车轮2 天前
CSS 预处理器:Sass的基本用法、核心特性
css·sass
清灵xmf3 天前
CSS field-sizing 让表单「活」起来
前端·css·field-sizing
面向星辰3 天前
css选择器(继承补充)
前端·css
敲代码的嘎仔4 天前
JavaWeb零基础学习Day1——HTML&CSS
java·开发语言·前端·css·学习·html·学习方法
Tachyon.xue4 天前
Vue 3 项目集成 Element Plus + Tailwind CSS 详细教程
前端·css·vue.js