2. Flexbox布局:掌握主轴与交叉轴,实现弹性伸缩布局

Flexbox,全称 Flexible Box,说白了就是「弹性盒子」。

我刚开始做前端那会儿,布局全靠 float 和 position。每次做垂直居中,都得写一堆 hack 代码。后来 Flexbox 一出来,我整个人都舒服了。它解决了一个核心问题:让容器内的元素能自动适应空间,不管尺寸是固定的还是动态的。

2.1 核心概念:主轴与交叉轴

Flexbox 有两个轴,这是理解它的关键。

  • 主轴(Main Axis):由 flex-direction 决定。默认是水平方向(从左到右)。
  • 交叉轴(Cross Axis):垂直于主轴。主轴是水平,交叉轴就是垂直。

你想想看,这两个轴就像十字坐标。所有子元素的排列、对齐、换行,都围绕这两个轴展开。

核心公式:主轴控制排列方向,交叉轴控制对齐方式。

2.2 容器属性:掌控全局

先看容器(父元素)上的属性。我习惯把它们分成三组:方向、换行、对齐。

2.2.1 flex-direction:决定主轴方向

.container {
  display: flex;
  flex-direction: row;        /* 默认值,水平从左到右 */
  flex-direction: row-reverse; /* 水平从右到左 */
  flex-direction: column;      /* 垂直从上到下 */
  flex-direction: column-reverse; /* 垂直从下到上 */
}

嗯,这里要注意:row-reverse 和 column-reverse 不只是方向变了,起始点和结束点也互换了。我在项目中遇到过一个问题:用 row-reverse 做导航栏的右对齐,结果子元素的顺序全反了。后来我改用 justify-content: flex-end,才搞定。

2.2.2 flex-wrap:控制换行

.container {
  flex-wrap: nowrap;    /* 默认,不换行,强行压缩 */
  flex-wrap: wrap;      /* 换行,从上到下 */
  flex-wrap: wrap-reverse; /* 换行,从下到上 */
}

默认的 nowrap 会让所有子元素挤在一行。如果内容太多,子元素会被压缩。我曾经踩过一个坑:卡片列表用了 nowrap,结果小屏上卡片被压成了细条,文字都叠在一起了。所以做响应式布局时,flex-wrap: wrap 几乎是标配。

2.2.3 justify-content:主轴对齐

.container {
  justify-content: flex-start;   /* 默认,起始端对齐 */
  justify-content: flex-end;     /* 结束端对齐 */
  justify-content: center;       /* 居中 */
  justify-content: space-between; /* 两端对齐,中间等距 */
  justify-content: space-around;  /* 每个元素两侧间距相等 */
  justify-content: space-evenly;  /* 所有间距完全相等 */
}

我个人最常用的是 space-between 和 center。比如做导航栏,左边 logo、右边菜单,用 space-between 一行代码搞定。

2.2.4 align-items:交叉轴对齐

.container {
  align-items: stretch;    /* 默认,拉伸填满 */
  align-items: flex-start; /* 起始端对齐 */
  align-items: flex-end;   /* 结束端对齐 */
  align-items: center;     /* 居中 */
  align-items: baseline;   /* 基线对齐 */
}

垂直居中?align-items: center 就完了。以前用 position: absolute 加负 margin 的日子,一去不复返了。

2.2.5 align-content:多行对齐

这个属性只在 flex-wrap: wrap 且有多行时生效。它控制的是整行在交叉轴上的分布。

.container {
  align-content: stretch;      /* 默认 */
  align-content: flex-start;
  align-content: flex-end;
  align-content: center;
  align-content: space-between;
  align-content: space-around;
}

小技巧:如果 align-content 没效果,先检查一下 flex-wrap 是不是 wrap,以及容器高度是否大于子元素总高度。

2.3 项目属性:精细控制每个元素

容器属性管全局,项目属性管个体。我一般用这三个:flex、align-self、order。

2.3.1 flex:伸缩因子

flex 是 flex-grow、flex-shrink、flex-basis 的缩写。我建议直接写 flex 简写,别拆开写,容易乱。

.item {
  flex: 1;           /* 等分剩余空间 */
  flex: 0 0 200px;   /* 固定宽度 200px,不伸缩 */
  flex: 1 1 auto;    /* 默认值 */
}

举个例子:三个卡片,想让中间那个占两倍空间,其他各占一倍。

.card { flex: 1; }
.card-center { flex: 2; }

我在项目中遇到过一个问题:用 flex: 1 做等分,结果内容太长的元素把其他元素挤变形了。后来加了 min-width: 0 才解决。嗯,这个坑很多人都会踩。

2.3.2 align-self:单独覆盖对齐

.item {
  align-self: auto;        /* 继承容器的 align-items */
  align-self: flex-start;
  align-self: flex-end;
  align-self: center;
  align-self: stretch;
  align-self: baseline;
}

比如一行里大部分元素居中,但某个元素想靠底部。用 align-self: flex-end 就行,不用改容器属性。

2.3.3 order:改变排列顺序

.item {
  order: 0;  /* 默认值,按源码顺序 */
  order: 1;  /* 排到后面 */
  order: -1; /* 排到前面 */
}

我曾经用 order 做移动端适配:PC 上图片在左边、文字在右边;移动端用 order 把图片调到文字下面。不用改 HTML 结构,爽得很。

注意:order 只改变视觉顺序,不影响键盘导航和屏幕阅读器的顺序。做无障碍时要小心。

2.4 实战:经典布局案例

2.4.1 圣杯布局(三栏自适应)

.container {
  display: flex;
  min-height: 100vh;
}
.left, .right {
  flex: 0 0 200px;  /* 固定宽度 */
}
.center {
  flex: 1;          /* 自适应 */
}

这个布局我用了好几年。左右固定,中间自适应。简单、稳定、不出错。

2.4.2 垂直居中

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

就两行代码。以前用 table-cell 或者 position 折腾半天,现在一行搞定。

2.4.3 等分布局

.container {
  display: flex;
}
.item {
  flex: 1;
}

不管几个子元素,自动等分。我做过一个仪表盘,6 个指标卡片,用这个方案,加一个减一个都不用改 CSS。

2.5 避坑指南

我总结几个常见坑,都是我曾经踩过的:

  • 子元素被压缩:给子元素加 flex-shrink: 0 或者 min-width。
  • 内容溢出:容器加 overflow: hidden 或 min-width: 0。
  • align-content 不生效:检查 flex-wrap 和容器高度。
  • order 导致焦点顺序错乱:尽量少用,或者配合 tabindex 调整。

核心原则:主轴管排列,交叉轴管对齐。记住这个,Flexbox 就掌握了一半。

2.6 知识体系图

Flexbox 布局 容器属性 flex-direction flex-wrap justify-content align-items align-content 项目属性 flex(伸缩因子) align-self order 核心概念:主轴 vs 交叉轴 主轴:排列方向(flex-direction) 交叉轴:对齐方式(align-*)

这张图把 Flexbox 的核心脉络理清了。左边是容器属性,右边是项目属性,下面是主轴与交叉轴。你照着这个结构去学,不会乱。

我的建议:别死记硬背属性值。打开浏览器开发者工具,边调边看效果。Flexbox 是「所见即所得」的,调几次就熟了。

好了,Flexbox 的核心内容就这些。主轴与交叉轴、容器与项目属性、常见布局与避坑,你都掌握了。下一节我们聊 Grid 布局,那又是另一个维度了。

可可精品资料库