自在学

我们与你共同进步

  • 分类课程
  • 文章
  • 工作台
  • 订阅

  • 关于我们
  • 隐私政策
  • 使用条款

探索

  • 分类课程
  • 文章
  • 工作台
  • 订阅

网站信息

  • 关于我们
  • 隐私政策
  • 使用条款

加入社区

自在学学习社区微信二维码

微信扫码,交流学习

株洲市自在学教育科技有限公司© 2025 - 2026 版权所有

© 2025 - 2026 株洲市自在学教育科技有限公司 版权所有

湘公网安备43020302000292号|湘ICP备2025148919号-1
分类课程工作台文章订阅
分类课程工作台文章价格

CSS 样式设计

  1. 01CSS 基础:从规则语法到样式接入
  2. 02CSS 选择器:从“选中谁”到“按结构精准定位”
  3. 03伪类与伪元素:把状态、结构与局部内容交给 CSS
  4. 04CSS 优先级、继承与层叠:浏览器到底听谁的
  5. 05CSS 值与单位:从“写得出来”到“算得明白”
  6. 06CSS 视觉格式化:从一个盒子到一行文字
  7. 07CSS 盒子外圈全解:内边距、边框、轮廓与外边距
  8. 08CSS 背景:从一层底色到完整的视觉系统
  9. 09CSS 渐变:从色标几何到可复用图案
  10. 10浮动与定位:从文字环绕到精确层叠
  11. 11Flexbox:从轴线理解弹性布局
  12. 12CSS Grid:从网格线到子网格的完整布局指南
  13. 13CSS 表格布局:从格式化结构到尺寸算法
  14. 14CSS 字体系统:从字体回退到可变字体
  15. 15CSS 文本排版:从行内方向到纵排书写的完整指南
  16. 16列表、生成内容与计数系统:让浏览器替你维护编号
  17. 17CSS 变换:从二维坐标到完整的 3D 场景
  18. 18CSS 过渡:让状态变化有节奏
  19. 19CSS 动画:从关键帧到可访问、可维护的动效系统
  20. 20CSS 视觉合成全指南:滤镜、混合、形状、裁剪与遮罩
正在加载课程章节内容
课程编程CSS 样式设计Flexbox:从轴线理解弹性布局

Flexbox:从轴线理解弹性布局

导航、工具栏、卡片列表和表单按钮区都有一个共同点:一组相邻元素需要沿着一个方向排列,还要根据空间变化调整间距或尺寸。这正是 Flexbox 擅长处理的一维布局。

刚接触 Flexbox 时,属性看起来很多,其实可以先抓住三个问题:主轴朝哪里,剩余空间出现在哪条轴上,当前属性写在容器还是项目上。后面的换行、对齐和弹性尺寸,都是围绕这三个问题展开的。

Flexbox 主轴与交叉轴手绘示意

Flexbox 按一条轴分配空间。即使项目换成多行,每一行也会单独计算主轴尺寸和分布。如果布局要求行与列同时对齐到固定轨道,Grid 通常更合适。


建立弹性格式化上下文

把 display: flex 或 display: inline-flex 写在父元素上,这个父元素就成了弹性容器,它的直接子节点则成为弹性项目。两种写法的内部布局规则相同,差别在容器自身如何参与外部排版:flex 生成块级容器,通常会占据一整行;inline-flex 生成行内级容器,可以和文字或其他行内盒并排。

html
<nav class="site-nav">
  <a href="/">首页</a>
  <a href="/guides">指南</a>
  <a href="/about">关于</a>
</nav>
css
.site-nav {
  display: flex;
  gap: 0.75rem;
}

这里要留意“直接子节点”这个范围。链接内部的图标和文字仍按原来的规则排版,除非我们再把链接设为弹性容器。纯空白文本节点会被忽略,带内容的文本却可能形成无法直接选中的匿名弹性项目,所以需要参与布局的内容最好放进明确的元素中。

直接子元素进入弹性格式化上下文后会被“块化”。无论它原来是 span 还是 p,此时都按弹性项目参与排布。项目之间的外边距不会折叠,float 和 clear 不再影响弹性排布,vertical-align 也无法把项目推到容器底部。

1
下面哪一个元素会成为 .toolbar 的弹性项目?

方向、书写模式与两条轴

我们常把 row 直觉地理解成“从左到右”,但 Flexbox 并没有把这两个概念绑定在一起。flex-direction 的四个值需要结合 writing-mode 和 direction 来看:

  • row:主轴沿当前书写模式的行内方向。
  • row-reverse:与 row 使用同一条轴,但交换主轴起点和终点。
  • column:主轴沿块方向。
  • column-reverse:与 column 使用同一条轴,但交换主轴起点和终点。
css
.toolbar { display: flex; flex-direction: row; }
.sidebar { display: flex; flex-direction: column; }

项目从 main-start 沿主轴排向 main-end。允许换行后,新行再从 cross-start 沿交叉轴堆叠到 cross-end。主轴上的尺寸叫 main size,交叉轴上的尺寸叫 cross size。

在常见的横排、从左到右页面中,row 的主轴通常从左向右,交叉轴从上向下。换到 RTL 或竖排文本后,物理方向就会改变。因此,理解轴线比记住“横向”和“纵向”更可靠。

可以把 justify-content 记成主轴分布,把 align-* 记成交叉轴对齐。这样即使切换 flex-direction,判断方式也不会失效。

2
只要使用 flex-direction: row,主轴就永远从屏幕左侧指向右侧。

换行、反向换行与 flex-flow

默认值 flex-wrap: nowrap 会让所有项目留在同一条弹性行中。空间不够时,项目会先尝试收缩;如果内容最小尺寸或固定尺寸不允许继续缩小,内容就会溢出。改成 wrap 后,容器可以增加新的弹性行。wrap-reverse 同样允许换行,只是它交换了交叉轴的起点和终点,新行会向相反方向堆叠。

flex-flow 把 flex-direction 和 flex-wrap 合并到一条声明里,两个值的先后顺序不影响结果:

css
.cards {
  display: flex;
  flex-flow: row wrap;
  gap: 1rem;
}

反向排列改变的是视觉流向,不会改写 DOM。row-reverse 反转每一行的主轴方向,wrap-reverse 反转多行在交叉轴上的堆叠方向,两者也可以同时使用。

换行、主轴分布与交叉轴对齐手绘对照

3
关于 flex-wrap 的说法,哪些正确?

主轴分布:justify-content

justify-content 写在容器上,处理每一条弹性行在主轴上的剩余空间。它不会像 flex-grow 那样改变项目尺寸,而是移动整组项目,或者把空白分配到项目之间。

  • start / flex-start:项目贴近主轴起点。
  • end / flex-end:项目贴近主轴终点。
  • center:整组项目居中。
  • space-between:首尾贴边,中间间隔相等;一行只有一个项目时位于起点。
  • space-around:每个项目两侧分到相同份额,所以相邻项目之间的空白是边缘空白的两倍。
  • space-evenly:边缘与项目之间的所有间隔都相等。

left 和 right 指向固定的物理方向,在需要适配不同书写方向时,通常不如 start 和 end 合适。在 Flexbox 中,normal 的效果等同于从起点分布;把 stretch 用在 justify-content 上也不会拉长项目。项目若已通过增长占满主轴,justify-content 自然就没有空白可分了。

css
.actions {
  display: flex;
  justify-content: space-between;
}

如果容器禁止换行,而且项目总尺寸超过容器,start 通常会向主轴终点溢出,end 会向主轴起点溢出,center 则可能从两侧一起溢出。safe center 会在居中可能截断内容时尝试退回安全对齐;实际使用前,仍要在目标浏览器中确认支持情况。

4
要让一行的首项贴主轴起点、末项贴主轴终点,并让中间间隔相等,应使用 justify-content: ____。

交叉轴:align-items、align-self 与自动外边距

align-items 写在容器上,规定每一行中所有项目默认如何沿交叉轴对齐。某个项目需要单独调整时,再把 align-self 写在这个项目上,覆盖容器给出的默认值。常用值有 stretch、start、end、center 和 baseline。

在 Flexbox 中,normal 通常表现为 stretch。不过,只有项目的交叉轴尺寸是 auto 时,拉伸才会明显发生;项目已经设置固定高度,stretch 不会强行覆盖这个高度。

如果一行里混有不同字号的文字、输入框和按钮,可以试试 baseline。first baseline 与 last baseline 分别指定首基线和末基线。在列方向等无法建立合适基线的场景中,它们会回退到起点或终点对齐。

css
.profile-row {
  display: flex;
  align-items: center;
}
 
.profile-row .status {
  align-self: flex-start;
}

自动外边距也能直接参与空间分配。主轴上的 margin-inline-start: auto 会先吸收可用空间,于是项目被推向主轴终点。把交叉轴两侧的外边距都设为 auto,则可以让单个项目在交叉轴上居中。因为自动外边距会优先拿走剩余空间,后续的对齐属性可能已经无处可调。

5
容器使用 align-items: center,但希望其中一个项目单独贴近交叉轴起点,应给该项目设置什么?

多行整体:align-content、place-content 与 gap

align-content 处理的是多条弹性行整体在交叉轴上的剩余空间。要看到效果,需要同时满足三个条件:容器允许换行,内容确实形成了多行,而且交叉轴上还有额外空间。单行容器通常看不出变化。

可用值包括 start、end、center、space-between、space-around、space-evenly 和 stretch。区分它和 align-items 的办法很直接:前者移动或拉开整行,后者对齐每一行内部的项目。

place-content 可以同时设置 align-content 和 justify-content。只写一个值时,两者使用同一个值;写两个值时,第一个控制交叉轴上的行分布,第二个控制主轴上的项目分布。

css
.gallery {
  display: flex;
  flex-wrap: wrap;
  min-height: 28rem;
  place-content: space-between center;
  gap: 1rem 1.5rem;
}

gap 是 row-gap 和 column-gap 的简写。它只在项目或弹性行之间留出固定间隔,不会给容器边缘增加空白,也没有外边距折叠的问题。在行方向的换行布局里,row-gap 通常控制行间距,column-gap 控制同一行中的项目间距。遇到其他方向时,再结合实际的行列关系判断。

6
单行 Flexbox 中,align-content: center 可以替代 align-items: center 来实现项目交叉轴居中。

交互实验:观察轴线与空间分配

下面这个实验把方向、换行、主轴分布和交叉轴对齐放在一起。你可以先保持 row 调整各项,再切到 column。这时原本的横向、纵向判断会跟着主轴改变,前面关于轴线的规则也会更直观。

7
在上面的实验中,哪些改动会改变主轴的物理方向?

弹性尺寸:basis、grow 与 shrink

计算弹性尺寸时,每个项目会先得到一个弹性基础尺寸。随后,浏览器判断主轴空间是有剩余还是不够,再进入增长或收缩阶段。flex-basis 指定空间分配前的主轴尺寸:主轴是行时,它接近起始宽度;主轴是列时,它接近起始高度。

  • flex-basis: auto:优先采用主轴方向显式 width/height,没有时参考内容。
  • 长度或百分比:直接作为基础尺寸;百分比相对容器内部主轴尺寸计算。
  • content、max-content、min-content 等内容关键字:按内容的内在尺寸求基础值。
  • 0:从零基础分配可用空间,常用于按增长因子得到比例列。

当所有基础尺寸的总和小于容器时,多出来的空间会按照 flex-grow 的比例分配。下图中有 300px 剩余空间,增长因子是 1:2:3,三个项目因此分别得到 50px、100px 和 150px,再把这些数值加到各自 200px 的基础尺寸上。

Flexbox 剩余空间按增长因子分配

基础尺寸总和超过容器时,就会出现负剩余空间,项目进入收缩阶段。这里不能只看 flex-shrink,收缩权重近似由 flex-shrink × flex-basis 决定。两个项目的收缩因子即使相同,基础尺寸更大的那个通常也要缩减更多。

实际计算还会受到 min-width、max-width 等边界影响。项目一旦碰到边界,浏览器会冻结它,再把尚未解决的差额分给其他项目。内容复杂时,一次简单的比例计算很难准确预测最终尺寸,最好在真实容器中检查结果。

css
.main { flex: 1 1 36rem; }
.aside { flex: 0 1 18rem; }

弹性项目的自动最小主轴尺寸经常由内容决定,所以设置了 flex-shrink: 1,项目仍可能溢出。需要让内容继续收缩时,行方向的项目通常要加 min-width: 0,列方向则对应 min-height: 0。

8
三个项目的 flex-basis 均为 200px,容器宽 900px,grow 比例为 1:2:3。第二项最终宽度是 ____px。

flex 简写与响应式模式

flex 依次表示 flex-grow flex-shrink flex-basis。把三段都写出来,阅读时最容易确认每个项目如何增长、收缩,以及从什么基础尺寸开始计算:

css
.card { flex: 1 1 18rem; }

常用预设的含义如下:

  • flex: initial → 0 1 auto:不主动增长,空间不足时允许收缩。
  • flex: auto → 1 1 auto:以内容或显式尺寸为基础,既增长也收缩。
  • flex: none → 0 0 auto:既不增长也不收缩。
  • flex: 1 → 常见计算行为接近 1 1 0%:从近零基础平分可用空间,而不是简单等同于 flex-grow: 1。

flex: 1 1 auto 会先保留各项目在内容或宽度上的差异,再分配剩余空间;flex: 1 1 0 则更接近等比分列。两种写法都可能被内容最小尺寸限制。

可换行的卡片列表常用 flex: 1 1 18rem。它表达得很清楚:项目的理想基础尺寸约为 18rem,可以增长,也可以收缩;当前行放不下时就换到下一行。相比手动计算百分比宽度,这种写法更能适应容器变化。

9
希望三列尽量按 1:1:1 分配容器空间,而不以各自内容宽度作为基础,最合适的是哪组?

项目边界、绝对定位与溢出排查

直接子元素改成绝对定位后,会脱离弹性布局,不再参与弹性行的空间分配。它的静态位置仍可能受到容器 justify-content 和自身 align-self 的影响;一旦写了 inset、top、left 等偏移,就按照定位规则放置。order 也可能改变它与兄弟元素的绘制先后,不过层叠关系应该交给定位和 z-index 等规则处理。

项目明明允许收缩却仍然溢出时,可以按下面的顺序排查:

  1. 确认主轴方向,行方向看 min-width,列方向看 min-height。
  2. 检查长单词、图片原始尺寸、white-space: nowrap 与固定宽度。
  3. 对承载可溢出内容的项目尝试 min-width: 0,并在内部设置合理的 overflow。
  4. 检查是否有项目使用 flex: none 或 flex-shrink: 0。
  5. 记得 gap、边框、内边距也占空间。
css
.shell { display: flex; }
.content { flex: 1 1 auto; min-width: 0; }
.content pre { overflow: auto; }
10
给弹性项目设置 position: absolute 后,它仍会占用弹性行空间,只是画面位置发生改变。

order、反向排列与可访问性

order 的初始值是 0,也可以设置为负数或正数。浏览器先按 order 从小到大排列不同的顺序组,同一组内仍然遵循源码顺序。

row-reverse、column-reverse 和 order 都能改变视觉顺序,却通常不会同步改变 DOM、键盘焦点顺序或辅助技术的读取顺序。也就是说,画面看起来重新排列了,实际的交互顺序可能仍停留在原来的结构中。

Flexbox 视觉顺序、键盘顺序与阅读顺序

css
.tabs { display: flex; }
.tabs .is-current { order: -1; }

这段代码会让当前标签在视觉上排到最前面,但用户按 Tab 键时,焦点仍可能按源码顺序移动,于是屏幕上的焦点会来回跳动。我们应先让 HTML 表达正确的逻辑和阅读顺序,再用 CSS 做不会妨碍理解的视觉调整。不要用 order 把页脚移到标题前面,也不要用反向排列掩盖错误的 DOM 顺序。

11
使用 order 或 row-reverse 前,必须考虑哪些风险?

综合实验:弹性参数与视觉重排

这个实验可以切换项目的 flex 配置,并观察实际宽度如何变化。打开“视觉反转”后,再按 Tab 键依次访问按钮。你会看到视觉顺序和焦点顺序可能出现分歧,这也是结构顺序不能交给 CSS 修补的原因。

12
当结构顺序本身不符合阅读逻辑时,最可靠的修复是调整 ____,而不是依赖 order。

写布局时的检查顺序

实际写 Flexbox 时,我们可以从轴线开始检查。先在父元素上建立弹性容器,再用 flex-direction 确定主轴,用 flex-wrap 决定是否允许增加弹性行。主轴上的剩余空间由 flex 和 justify-content 处理;一行内部的交叉轴对齐看 align-items 或 align-self,多行整体的分布看 align-content。项目之间的固定间隔可以交给 gap。

布局完成后,再检查项目的最小尺寸和溢出行为。只要使用了反向排列或 order,还要用键盘走一遍焦点顺序,确认视觉变化没有破坏阅读和操作逻辑。

css
.card-list {
  display: flex;
  flex-flow: row wrap;
  gap: 1rem;
}
 
.card {
  flex: 1 1 18rem;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
 
.card__actions {
  margin-top: auto;
  display: flex;
  gap: 0.5rem;
}

一段容易维护的 Flexbox 代码,通常不会依赖固定的左右方向,也不会用 order 修补结构。它会明确处理项目的收缩边界,并能说明每一处剩余空间由哪个属性分配。

13
一个已换成多行且有固定高度的卡片容器,需要把多条行整体在交叉轴居中,应使用哪个属性?
上一章浮动与定位:从文字环绕到精确层叠下一章CSS Grid:从网格线到子网格的完整布局指南