技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTCSS

Flex 布局

所属馆藏
CSS
文件格式
Markdown
原始路径
CSS/14-Flex 布局
本文目录16 个章节
  1. 一、Flex 基本概念
  2. 二、Flex 容器属性
  3. 三、flex-direction:主轴方向
  4. 四、flex-wrap:项目是否换行
  5. 五、flex-flow:方向和换行的简写
  6. 六、justify-content:主轴对齐
  7. 七、align-items:交叉轴上的项目对齐
  8. 八、align-content:多条 Flex line 的交叉轴分布
  9. 九、gap:项目和 Flex line 之间的间距
  10. 十、Flex 项目属性
  11. 十一、flex-grow、flex-shrink 与换行的关系
  12. 十二、align-self:单独设置项目对齐方式
  13. 十三、常见问题和实用技巧
  14. 十四、Flex 布局与其他布局方式
  15. 总结
  16. 参考资料

Flex 布局

Category(分类): CSS Status: 已整理

Flex(Flexible Box Layout,弹性盒布局)是一种一维布局模型,主要用于安排一行或一列中的项目。它可以根据容器剩余空间放大或缩小项目,也可以在项目较多时换行。

Flex 适合处理:

  • 导航栏和工具栏;
  • 水平或垂直居中;
  • 等分布局;
  • 两端对齐;
  • 卡片列表和响应式换行;
  • 项目尺寸不固定的布局。

一、Flex 基本概念

Flex 容器中主要有两条轴:

  • 主轴(main axis):项目排列的方向;
  • 交叉轴(cross axis):与主轴垂直的方向。

容器中的直接子元素称为 Flex item。项目在主轴上占据的尺寸称为 main size,在交叉轴上占据的尺寸称为 cross size

不能简单地把宽度理解成 main size、高度理解成 cross size。默认 flex-direction: row 时,主轴通常是水平方向;如果设置为 column,主轴就变成垂直方向。

此外,rowcolumn 依据当前书写模式决定方向。在默认的水平、从左到右书写模式中,row 通常从左向右排列;在 RTL 或垂直书写模式中,起点和方向可能不同。

Flex 容器、主轴和交叉轴

二、Flex 容器属性

1. 创建 Flex 容器

任何元素都可以设置为 Flex 容器:

.container {
  display: flex;
}

.inline-container {
  display: inline-flex;
}
  • flex:容器本身表现为块级盒子;
  • inline-flex:容器本身表现为行内级盒子;
  • 两者的直接子元素都会按照 Flex 规则布局。

Flex 容器的直接子元素会成为 Flex item。Flex item 上的 floatclearvertical-align 不参与 Flex 布局,但这些属性并不会因此在整个文档中失效。

三、flex-direction:主轴方向

.container {
  flex-direction: row;
}

可选值:

row | row-reverse | column | column-reverse

默认值是 row

1. row

沿当前书写模式的行向轴排列。在默认水平从左到右的页面中,通常表现为从左到右:

.container {
  display: flex;
  flex-direction: row;
}

row 排列

2. row-reverse

反转主轴的起点。在默认从左到右的页面中,通常表现为从右到左:

.container {
  display: flex;
  flex-direction: row-reverse;
}

row-reverse 排列

3. column

沿块向轴排列,默认水平书写模式下通常表现为从上到下:

.container {
  display: flex;
  flex-direction: column;
}

column 排列

4. column-reverse

反转块向轴的起点,默认水平书写模式下通常表现为从下到上:

.container {
  display: flex;
  flex-direction: column-reverse;
}

column-reverse 排列

row-reversecolumn-reverse 只改变视觉排列方向,不会改变 DOM 顺序。涉及键盘操作、屏幕阅读器或有序内容时,不建议仅依赖反向排列表达语义顺序。

四、flex-wrap:项目是否换行

.container {
  flex-wrap: nowrap;
}

可选值:

nowrap | wrap | wrap-reverse

默认值是 nowrap

1. nowrap

所有项目尽量放在同一条 Flex line 中。空间不足时,项目可能根据 flex-shrink 缩小,也可能因为最小尺寸限制而溢出:

.container {
  display: flex;
  flex-wrap: nowrap;
}

因此不能简单地说 nowrap 一定会让项目自动缩小。是否缩小还取决于 flex-shrinkmin-widthmin-height 和项目内容。

nowrap

2. wrap

主轴空间不足时创建新的 Flex line:

.container {
  display: flex;
  flex-wrap: wrap;
}

在默认水平书写模式下,新的行通常从上到下生成。

wrap

3. wrap-reverse

允许换行,并反转交叉轴方向:

.container {
  display: flex;
  flex-wrap: wrap-reverse;
}

在默认水平书写模式下,新的行通常从下到上生成。

wrap-reverse

wrap 并不意味着 flex-shrink 永远不会生效。每一条 Flex line 都会独立分配空间;如果某一行仍然存在负剩余空间,项目仍可能缩小。

五、flex-flow:方向和换行的简写

flex-flowflex-directionflex-wrap 的简写:

.container {
  flex-flow: row wrap;
}

等价于:

.container {
  flex-direction: row;
  flex-wrap: wrap;
}

默认值为:

row nowrap

当需要同时设置方向和换行时,使用 flex-flow 可以让代码更紧凑;是否使用它取决于团队的可读性偏好。

六、justify-content:主轴对齐

justify-content 定义项目在主轴上的分布方式:

.container {
  justify-content: flex-start;
}

常见取值包括:

flex-start | flex-end | center
space-between | space-around | space-evenly
start | end

默认值为 flex-start

以下示例假设主轴为水平方向:

1. flex-start

项目靠主轴起点排列:

.container {
  display: flex;
  justify-content: flex-start;
}

flex-start

2. flex-end

项目靠主轴终点排列:

flex-end

3. center

项目在主轴方向居中:

center

4. space-between

两端项目分别贴近容器起点和终点,项目之间的剩余空间相等:

space-between

5. space-around

每个项目两侧的外部间隔相等,因此相邻项目之间的间隔通常是边缘间隔的两倍:

space-around

6. space-evenly

项目之间以及项目与容器边缘之间的间隔都相等:

.container {
  justify-content: space-evenly;
}

justify-content 分配的是主轴剩余空间。如果项目设置了自动外边距,例如 margin-left: auto,自动外边距会优先消耗剩余空间。

七、align-items:交叉轴上的项目对齐

align-items 定义同一条 Flex line 中项目在交叉轴上的对齐方式:

.container {
  align-items: stretch;
}

常见取值包括:

normal | stretch | flex-start | flex-end
center | baseline | start | end

默认值为 stretch

以下示例假设主轴为水平方向,因此交叉轴是垂直方向。

1. stretch

当容器交叉轴尺寸确定,项目的交叉轴尺寸为 auto,且没有被最小/最大尺寸限制时,项目会拉伸以填充所在 Flex line 的交叉轴尺寸:

.container {
  display: flex;
  height: 100px;
  align-items: stretch;
}

.item {
  /* 不设置 height,或设置为 auto */
}

它不一定会让项目无条件占满整个容器高度;多行 Flex 布局还要考虑每一条 Flex line 的尺寸。

align-items: stretch

2. flex-start

项目靠交叉轴起点对齐:

flex-start

3. flex-end

项目靠交叉轴终点对齐:

flex-end

4. center

项目在交叉轴方向居中:

center

5. baseline

项目按照基线对齐,常用于文字或带文本的控件:

.container {
  display: flex;
  align-items: baseline;
}

基线不等于元素底边。不同字体、图片、输入框和没有文本基线的项目可能使用不同的基线替代规则。

baseline

八、align-content:多条 Flex line 的交叉轴分布

align-content 用于设置多条 Flex line 在交叉轴上的分布方式:

.container {
  align-content: stretch;
}

常见取值包括:

normal | stretch | flex-start | flex-end | center
space-between | space-around | space-evenly
start | end

默认值为 normal,在 Flex 布局中通常表现为 stretch

只有在以下情况下才容易观察到它的效果:

  • 容器允许换行;
  • 实际产生了两条或更多 Flex line;
  • 交叉轴尺寸明确;
  • Flex lines 之间存在剩余空间。

例如:

.container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
  height: 300px;
}

这里对齐的是多条 Flex line,不是项目本身。align-items 负责一条 Flex line 内项目的对齐,align-content 负责多条 Flex line 之间的分布。

align-content: stretch 的多行效果

当项目设置了固定高度时,align-content: stretch 主要改变 Flex line 的分布;项目未设置交叉轴尺寸时,还可能受到 align-items: stretch 的影响。

项目没有固定高度时的效果

其他常见取值:

.container {
  align-content: flex-start;
}

align-content: flex-start

.container {
  align-content: flex-end;
}

align-content: flex-end

.container {
  align-content: center;
}

align-content: center

.container {
  align-content: space-between;
}

align-content: space-between

.container {
  align-content: space-around;
}

align-content: space-around

九、gap:项目和 Flex line 之间的间距

现代浏览器支持在 Flex 容器中使用 gap

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px;
}

第一个值是行间距,第二个值是列间距。也可以分别使用:

.container {
  row-gap: 16px;
  column-gap: 24px;
}

gap 只设置项目之间的间距,不会自动产生容器外侧的留白。与给每个项目设置外边距相比,gap 不需要额外处理首尾项目的边距。

十、Flex 项目属性

Flex item 常用的属性包括:

  1. order
  2. flex-basis
  3. flex-grow
  4. flex-shrink
  5. flex
  6. align-self

1. order:视觉排列顺序

.item {
  order: 0;
}

order 默认值为 0。数值越小,视觉排列越靠前;数值相同时,按照源文档顺序排列。

.item--first {
  order: -1;
}

.item--last {
  order: 1;
}

order 调整视觉顺序

order 不会改变 DOM 顺序、键盘导航顺序和屏幕阅读器阅读顺序。语义顺序应优先通过 HTML 结构表达。

2. flex-basis:Flex 基础尺寸

.item {
  flex-basis: 200px;
}

flex-basis 定义项目在分配主轴剩余空间之前的基础尺寸。它沿主轴生效:

  • 主轴为 row 时,通常对应宽度方向;
  • 主轴为 column 时,通常对应高度方向。

常见取值:

auto | content | <length> | <percentage>

auto 会参考项目的主轴尺寸属性,例如 row 方向下的 width;如果主轴尺寸也是 auto,则可能根据内容计算。

.item {
  flex-basis: 200px;
  width: 400px;
}

flex-basis 不是 auto 时,它通常优先于主轴尺寸属性,但 min-*max-* 仍可能限制最终尺寸。

flex-basis: 00% 常用于让项目从零基础尺寸开始分配剩余空间,但最终尺寸仍可能受 min-width: auto、内容最小尺寸和最小/最大尺寸限制。

3. flex-grow:放大比例

.item {
  flex-grow: 0;
}

默认值为 0,表示有剩余空间时项目不会主动放大。

当一条 Flex line 的项目基础尺寸之和小于容器主轴尺寸时,会产生正剩余空间。flex-grow 大于 0 的项目可以按比例分配这部分空间:

.item {
  flex-grow: 1;
}

.item--large {
  flex-grow: 2;
}

如果项目的 flex-grow 都是 1,通常会均分剩余空间;如果一个项目为 2、其他项目为 1,它通常分得两倍的剩余空间。

实际分配还会受到 min-widthmax-widthmin-heightmax-height 等约束影响,并且多行 Flex 会按行分别计算。

flex-grow

4. flex-shrink:收缩比例

.item {
  flex-shrink: 1;
}

默认值为 1。当一条 Flex line 的基础尺寸之和超过容器主轴尺寸时,项目可能缩小。负数对 flex-shrink 无效。

.item--fixed {
  flex-shrink: 0;
}

flex-shrink 并不是简单地让所有项目同比例缩小。实际负空间通常按照以下因素加权分配:

flex-shrink × flex base size

项目基础尺寸越大,即使 flex-shrink 值相同,也可能承担更多缩小量。同时,自动最小尺寸和 min-width 可能阻止项目继续缩小。

flex-shrink

5. flex:三个属性的简写

flex 是以下三个属性的简写:

.item {
  flex: <flex-grow> <flex-shrink> <flex-basis>;
}

常见写法:

.item {
  flex: 1 1 200px;
}

等价于:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 200px;
}

flex 的默认值是:

.item {
  flex: 0 1 auto;
}

常用快捷值:

写法常见等价形式含义
flex: 11 1 0%从相同的基础尺寸开始分配空间,常用于等分
flex: auto1 1 auto参考项目原始尺寸并允许伸缩
flex: none0 0 auto不放大、不缩小,保留原始尺寸
flex: 0 1 auto默认值不放大,空间不足时允许缩小

下面是几个常见展开形式:

/* 一个非负数字 */
.item-a {
  flex: 1;
  /* 常见计算结果:1 1 0% */
}

/* 两个非负数字 */
.item-b {
  flex: 2 3;
  /* 2 3 0% */
}

/* 一个数字和一个长度 */
.item-c {
  flex: 2 32px;
  /* 2 1 32px */
}

实际项目中建议使用 flex 简写表达完整意图,而不是随意混用 widthflex-basis 和三个独立的 Flex 属性。

十一、flex-growflex-shrink 与换行的关系

可以按每条 Flex line 的空间情况理解:

  1. flex-wrap: nowrap 且基础尺寸之和小于容器尺寸时,存在正剩余空间,flex-grow 可能生效;
  2. flex-wrap: nowrap 且基础尺寸之和大于容器尺寸时,存在负剩余空间,flex-shrink 可能生效;
  3. flex-wrap: wrap 时,项目会先根据换行规则形成多条 Flex line;每一行再单独计算剩余空间;
  4. 某一行有正剩余空间时,该行的 flex-grow 可能生效;
  5. 某一行有负剩余空间时,该行的 flex-shrink 仍可能生效;
  6. flex-growflex-shrink 通常不会在同一次空间分配中同时作为主要方向生效,但换行后的不同 Flex line 可以分别出现不同情况。

示例:

.container {
  display: flex;
  flex-wrap: wrap;
  width: 320px;
}

.item {
  flex: 1 1 180px;
  min-width: 0;
}

这里每一行都可能根据实际项目数量产生放大或缩小。不能简单认为 wrap 后空间永远足够。

十二、align-self:单独设置项目对齐方式

align-self 可以覆盖单个项目的 align-items 设置:

.container {
  display: flex;
  align-items: flex-start;
}

.item--center {
  align-self: center;
}

常见取值包括:

auto | normal | stretch | flex-start | flex-end
center | baseline | start | end

默认值为 auto。它会使用父 Flex 容器的 align-items 计算结果;这不是普通 CSS 意义上的属性继承。

align-items 作用于容器中的项目,align-self 只作用于当前项目:

align-self 单独覆盖对齐方式

十三、常见问题和实用技巧

1. 文本或长单词导致 Flex 项目无法缩小

Flex item 默认的自动最小尺寸可能来自内容的最小尺寸。长文本、长 URL 或不可换行内容可能导致项目溢出:

.item {
  min-width: 0;
  overflow-wrap: anywhere;
}

对于垂直 Flex 容器中的滚动区域,通常还需要:

.column-container {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

2. 使用 margin: auto 推开项目

.header {
  display: flex;
  align-items: center;
}

.header__actions {
  margin-left: auto;
}

在主轴方向上,自动外边距会优先吸收剩余空间,常用于把操作按钮推到右侧。

3. 项目垂直居中

.container {
  display: flex;
  align-items: center;
  justify-content: center;
}

justify-content 控制主轴,align-items 控制交叉轴。改变 flex-direction 后,两者所对应的物理方向也会改变。

4. gap 和外边距的选择

优先使用 gap 表示项目之间的间距:

.list {
  display: flex;
  gap: 16px;
}

只有需要让某个项目自动占据剩余空间,或需要与外部布局交互时,才使用 margin: auto 或普通外边距。

5. 注意视觉顺序和语义顺序

如果页面内容有明确的阅读顺序,应优先调整 HTML 结构,不要依赖 orderrow-reverse 代替语义结构。

十四、Flex 布局与其他布局方式

Flex 是一维布局,适合处理单行或单列中的项目分布。Grid 是二维布局,更适合同时控制行和列。

  • 一行导航栏:优先考虑 Flex;
  • 多行多列且行列需要同时对齐:优先考虑 Grid;
  • 简单的项目间距:优先使用 gap
  • 复杂图形或精确路径:考虑 SVG;
  • 内容语义顺序:优先由 HTML 结构保证。

总结

Flex 布局的核心不是记住几个对齐属性,而是理解以下关系:

  • flex-direction 决定主轴方向;
  • flex-wrap 决定是否生成多条 Flex line;
  • justify-content 控制主轴上的剩余空间分布;
  • align-items 控制一条 Flex line 内项目的交叉轴对齐;
  • align-content 控制多条 Flex line 的交叉轴分布;
  • flex-basis 确定项目的基础尺寸;
  • flex-grow 分配正剩余空间;
  • flex-shrink 分配负剩余空间;
  • align-self 覆盖单个项目的交叉轴对齐;
  • order 只改变视觉顺序,不改变 DOM 和无障碍阅读顺序。

实际开发中,应结合项目的书写模式、最小尺寸、内容长度、换行策略和可访问性进行判断,而不要把 Flex 属性简单理解成只针对水平布局的固定规则。

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS