Flexbox(Flexible Box Layout)是 CSS3 引入的一维布局模型,专门用于在容器的主轴方向上分配空间和对齐元素。在 Flexbox 出现之前,实现垂直居中、等分列、动态分配宽度这些需求往往需要各种 hack 技巧,比如浮动加清除浮动、表格布局、行内块加空白符处理等。Flexbox 让这些曾经的难题变得轻而易举。

基本概念

Flexbox 的核心是两个角色:弹性容器(Flex Container)和弹性项目(Flex Item)。将一个元素的 display 设为 flexinline-flex,它就变成了弹性容器,其直接子元素自动成为弹性项目。

.container {
  display: flex;
  /* 此时 .container 是弹性容器 */
  /* 其直接子元素成为弹性项目 */
}

Flex 布局围绕两根轴运作:主轴(Main Axis)是弹性项目排列的方向,默认是水平从左到右;交叉轴(Cross Axis)与主轴垂直,默认是从上到下。理解这两根轴是掌握 Flexbox 的关键。

容器属性

flex-direction

定义主轴方向,决定弹性项目如何排列:

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

justify-content

控制弹性项目在主轴上的对齐方式和剩余空间分配:

.container {
  display: flex;
  justify-content: flex-start;    /* 默认,起始对齐 */
  justify-content: flex-end;      /* 末尾对齐 */
  justify-content: center;        /* 居中对齐 */
  justify-content: space-between; /* 两端对齐,项目间等距 */
  justify-content: space-around;  /* 每个项目两侧等距 */
  justify-content: space-evenly;  /* 完全均匀分布 */
}

align-items

控制弹性项目在交叉轴上的对齐方式:

.container {
  display: flex;
  align-items: stretch;     /* 默认,拉伸填满容器高度 */
  align-items: flex-start;  /* 交叉轴起始对齐 */
  align-items: flex-end;    /* 交叉轴末尾对齐 */
  align-items: center;      /* 交叉轴居中 */
  align-items: baseline;    /* 按文本基线对齐 */
}

flex-wrap 与 gap

默认情况下弹性项目不会换行。设置 flex-wrap: wrap 后,当项目总宽度超出容器时自动换行。gap 属性则直接控制项目之间的间距:

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px; /* 项目之间的间距,行和列都生效 */
}

项目属性

flex-grow、flex-shrink、flex-basis

这三个属性共同控制弹性项目如何伸缩。通常推荐使用简写属性 flex

.item {
  /* flex-grow: 放大比例,默认 0(不放大) */
  /* flex-shrink: 缩小比例,默认 1(等比缩小) */
  /* flex-basis: 初始大小,默认 auto */

  flex: 0 1 auto;  /* 默认值,不放大、可缩小 */
  flex: 1;         /* 等价于 flex: 1 1 0%,等分空间 */
  flex: 2;         /* 占据 flex:1 项目两倍的空间 */
  flex: auto;      /* 等价于 flex: 1 1 auto */
  flex: none;      /* 等价于 flex: 0 0 auto,固定大小 */
}

order 与 align-self

order 可以改变项目的视觉排列顺序,默认值为 0,值越小越靠前。align-self 允许单个项目覆盖容器的 align-items 设置:

.item-first {
  order: -1; /* 排到最前面 */
}

.item-tall {
  align-self: stretch; /* 单独拉伸 */
}

常见布局模式

完美居中

Flexbox 实现居中只需三行代码,这是它最受欢迎的用法:

.center-box {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
}

导航栏布局

Logo 在左,导航链接在右,中间自动填充空间:

.navbar {
  display: flex;
  align-items: center;
  padding: 0 24px;
  height: 60px;
}

.navbar .logo {
  flex: none; /* Logo 固定宽度 */
}

.navbar .links {
  flex: 1; /* 链接区域占满剩余空间 */
  display: flex;
  justify-content: flex-end;
  gap: 20px;
}

卡片网格

等宽卡片自动换行排列,响应式无需媒体查询:

.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.card {
  flex: 1 1 300px; /* 最小宽度 300px,自动填充 */
  max-width: calc(50% - 12px); /* 最多两列 */
  padding: 20px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
}

等高列布局

传统 CSS 实现等高列需要各种技巧,而 Flexbox 默认就支持:

.columns {
  display: flex;
  gap: 20px;
}

.column {
  flex: 1;
  /* 所有列自动等高,无需额外设置 */
}

注意事项

Flexbox 是一维布局模型,适合处理单行或单列的场景。如果需要同时控制行和列,应该使用 CSS Grid。此外,flex 简写属性中只写一个数值时(如 flex: 1),浏览器会将 flex-basis 设为 0% 而非 auto,这在某些场景下会影响项目内容的最小宽度计算,需要特别注意。

Flexbox 已经得到了所有现代浏览器的完整支持,在项目中可以放心使用。它极大地简化了 CSS 布局的复杂度,是每个前端开发者必须掌握的核心技能。