CSS3 布局系统

Flexbox + Grid——从"排列不了"到"想怎么排就怎么排"

用更少的代码,实现更灵活的页面布局

为什么需要布局

没有布局系统时,网页像记事本——内容只能从上到下堆砌

传统堆砌

内容1
内容2
内容3

→ 无法水平排列
→ 无法垂直居中
→ 无法等高列

现代布局

[导航] [导航] [导航]
[  侧栏  |    主内容  ]
[      页脚        ]

→ 水平排列 ✓
→ 垂直居中 ✓
→ 等高列   ✓
问题解决方案
元素水平排列Flexbox flex-direction: row
元素垂直居中Flexbox align-items: center
构建复杂网格Grid grid-template-areas
响应式适配Grid minmax() + auto-fit

传统布局痛点

在 Flexbox 和 Grid 出现之前,实现"垂直居中"需要多少代码?

传统居中(6 行)

.container {
  position: relative;
}
.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

需要绝对定位 + transform。translate 的百分比相对元素自身尺寸,所以不用量尺寸,但代码偏长。

Flexbox 居中(3 行)

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

三行搞定。不需要知道元素尺寸,动态内容也没问题。

布局技术演进:Table 布局 → Float 布局 → Position 布局 → Flexbox (2012) → Grid (2017)。关键转折点就是 Flexbox 和 Grid,彻底改变了 CSS 布局方式。

Part 1: Flexbox

一维布局模型——专注于在单个方向(行或列)上排列元素,特别擅长空间分配、对齐控制和顺序调整。

容器属性

flex-direction 定方向,justify-content 管主轴对齐,align-items 管交叉轴对齐,flex-wrap 控制换行。

项目属性

flex 控制空间分配比例,order 调整显示顺序 — 无需改 HTML 即可重排布局。

容器与项目

给父容器加 display: flex,它的直接子元素就变成了"弹性项目"

<div class="container">
  <div class="item">项目1</div>
  <div class="item">项目2</div>
  <div class="item">项目3</div>
</div>
.container {
  display: flex;  /* 启用 Flexbox */
  gap: 10px;      /* 项目间距 */
}
.item {
  padding: 20px;
  background: #007bff;
  color: white;
}
两个角色:① 容器(加 display: flex 的元素)—— 控制排列规则 ② 项目(直接子元素)—— 可以单独调整占比和顺序。

方向与主轴对齐

flex-direction 决定排列方向,justify-content 控制主轴上的对齐方式

flex-direction 方向

/* 水平排列(默认) */
flex-direction: row;
/* 水平反向 */
flex-direction: row-reverse;
/* 垂直排列 */
flex-direction: column;
/* 垂直反向 */
flex-direction: column-reverse;

justify-content 对齐

/* 左对齐(默认) */
justify-content: flex-start;
/* 居中 */
justify-content: center;
/* 两端对齐 */
justify-content: space-between;
/* 等间距 */
justify-content: space-around;
记忆口诀:flex-direction 定方向(主轴),justify-content 管主轴对齐,align-items 管交叉轴对齐。

交叉轴与换行

垂直居中只需要 align-items: center 一行——这就是 Flexbox 流行的原因

align-items 交叉轴对齐

/* 拉伸填满(默认) */
align-items: stretch;
/* 顶部对齐 */
align-items: flex-start;
/* 垂直居中(最常用) */
align-items: center;
/* 文本基线对齐 */
align-items: baseline;

flex-wrap 换行控制

/* 不换行(默认,可能溢出) */
flex-wrap: nowrap;
/* 自动换行 */
flex-wrap: wrap;
/* 反向换行 */
flex-wrap: wrap-reverse;

配合 gap 使用,换行后间距自动一致。

项目属性详解

flex 控制空间分配,order 控制显示顺序

flex 空间分配

/* 等分空间 */
.item { flex: 1; }

/* 比例分配 1:2:3 */
.a { flex: 1; }
.b { flex: 2; }
.c { flex: 3; }

/* 固定宽度 + 弹性 */
.sidebar { flex: 0 0 200px; }
.main    { flex: 1; }

order 显示顺序

/* 默认顺序 = DOM 顺序 */
.item { order: 0; }

/* 改变视觉顺序 */
.first  { order: 1; }
.second { order: 2; }
.third  { order: 3; }

DOM 顺序不变,视觉上按 order 值排列。适合响应式重排。

注意:flex: 1 是 flex-grow: 1; flex-shrink: 1; flex-basis: 0% 的简写。大多数情况直接用 flex: 1 或 flex: 2 就够了。

Part 2: Grid

二维布局系统——可以同时控制行和列,适合构建页面整体结构和复杂网格。

网格基础

grid-template-columns/rows 定义行列,fr 单位按比例分配空间,gap 控制间距。

高级用法

grid-template-areas 画蓝图、跨行跨列布局、auto-fit + minmax 无需媒体查询的响应式网格。

网格基础结构

给容器加 display: grid,然后用行列定义画出网格

.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;  /* 三等分列 */
  grid-template-rows: 100px 100px;      /* 两行,各100px */
  gap: 10px;
}

3 列 2 行网格与网格线编号

     列线 1     列线 2     列线 3     列线 4
        ↓         ↓         ↓         ↓
   ┌─────────┬─────────┬─────────┐ ← 行线 1
   │    1    │    2    │    3    │
   ├─────────┼─────────┼─────────┤ ← 行线 2
   │    4    │    5    │    6    │
   └─────────┴─────────┴─────────┘ ← 行线 3

引用某条网格线就能精确定位:grid-column: 1 / 3 表示从列线 1 跨到列线 3,也就是占第 1、2 两列。

fr 单位:fraction(份数),1fr 1fr 1fr 表示把可用空间平均分成 3 份。就像切蛋糕——1fr 2fr 1fr 就是 1:2:1 的比例。

列宽定义方式

Grid 提供四种定义列宽的方式,从固定到灵活

方式代码示例适用场景
固定宽度100px 200px 150px需要精确像素控制
比例分配1fr 2fr 1fr按比例分空间(最常用)
minmax()minmax(100px, 1fr)设最小/最大值
repeat()repeat(4, 1fr)重复相同模式
/* 四种写法对比 */
.fixed   { grid-template-columns: 100px 200px 150px; }
.ratio   { grid-template-columns: 1fr 2fr 1fr; }
.minmax  { grid-template-columns: minmax(100px, 1fr) 200px minmax(150px, 2fr); }
.repeat  { grid-template-columns: repeat(4, 1fr); }

命名区域布局

用 grid-template-areas 像画蓝图一样描述页面结构

.layout {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar main    main"
    "footer  footer  footer";
  grid-template-columns: 200px 1fr 1fr;
  grid-template-rows: 80px 1fr 60px;
  gap: 10px;
}

header  { grid-area: header; }
aside   { grid-area: sidebar; }
main    { grid-area: main; }
footer  { grid-area: footer; }
优势:一眼就能看出页面结构。想调整布局?只需改 grid-template-areas 里的字符串,不用动 HTML。同一个名字可以跨多列/多行。

网格间距控制

gap 统一控制行列间距,告别 margin 的各种坑

传统 margin 方式

/* 首尾元素有多余空白 */
.items > * {
  margin-right: 10px;
}
.items > *:last-child {
  margin-right: 0; /* 手动清除 */
}

gap 属性

.container {
  display: flex;
  gap: 10px;
  /* 就这一行,完事 */
}

/* 行列间距不同 */
.grid {
  row-gap: 10px;
  column-gap: 30px;
}
gap 同时适用于 Flexbox 和 Grid,是间距控制的现代标准方案。

跨行列布局

用 grid-column 和 grid-row 让元素横跨多列/多行

.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  gap: 10px;
}

/* 跨 3 列(整行) */
.feature {
  grid-column: 1 / 4;
}

/* 跨 2 行 */
.sidebar {
  grid-row: 2 / 4;
}

跨行跨列的最终效果

┌─────────────────────────────┐
│        特色内容(跨 3 列)       │  grid-column: 1 / 4
├──────────┬─────────┬─────────┤
│          │  内容 1  │  内容 2  │
│  侧边栏   ├─────────┼─────────┤
│ (跨 2 行) │  内容 3  │  内容 4  │  grid-row: 2 / 4
└──────────┴─────────┴─────────┘

把起止网格线写成 grid-column: 1 / 4、grid-row: 2 / 4,元素就会自动横跨对应的行列,其余格子由普通项目填充。

响应式图片墙

一行代码实现无需媒体查询的响应式网格

.gallery {
  display: grid;
  /* 核心:自动适应屏幕宽度 */
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 15px;
}
关键词作用
minmax(250px, 1fr)每列最小 250px,最大等分空间
auto-fit自动调整列数,填满可用空间
效果:小屏幕单列 → 中等屏幕双列 → 大屏幕三列或更多。完全不需要 @media。

Part 3: 现代辅助

这些 CSS 特性本身不构成独立布局系统,但能让 Flexbox 和 Grid 更强大、更简洁。

间距与比例

gap 统一控制间距,minmax + auto-fit 实现无需媒体查询的响应式网格。

宽高比与对齐

aspect-ratio 保持宽高比,place-items/place-content 简化对齐代码。

gap 间距控制

告别 margin 的首尾空白问题

传统 margin

/* 每个项目加右边距 */
.item { margin-right: 10px; }
/* 再清除最后一个的 */
.item:last-child {
  margin-right: 0;
}

首尾元素的间距需要特殊处理。

gap 属性

.container {
  display: flex;
  gap: 10px;
  /* 就这一行,完事 */
}

自动处理间距,首尾无多余空白。

gap 同时适用于 Flexbox 和 Grid,是间距控制的现代标准方案。

智能响应式网格

用 minmax() + auto-fit 替代一堆媒体查询

传统媒体查询

@media (max-width: 600px) {
  .grid {
    grid-template-columns: 1fr;
  }
}
@media (min-width: 601px)
  and (max-width: 900px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 901px) {
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

一行代码

.grid {
  display: grid;
  grid-template-columns:
    repeat(auto-fit,
      minmax(250px, 1fr));
}

效果完全相同,代码量减少 80%。

宽高比控制

保持视频容器或卡片的宽高比,告别 padding 技巧

传统 padding 技巧

.video-container {
  position: relative;
  width: 100%;
}
.video-container::before {
  content: "";
  display: block;
  padding-bottom: 56.25%;
  /* 9/16 = 0.5625 */
}
.video-content {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
}

aspect-ratio

/* 视频容器 16:9 */
.video-container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

/* 正方形卡片 */
.card {
  aspect-ratio: 1 / 1;
}

一行代码搞定。宽度变,高度自动跟。

对齐快捷方式

place-items 和 place-content 是对齐属性的简写

分开写(4 行)

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

简写(2 行)

.container {
  display: grid;
  place-items: center;
  /* = align-items + justify-items */
  place-content: center;
  /* = align-content + justify-content */
}
格式:place-items: [align] [justify]。只写一个值时两个方向都用同一个值。

Part 4: 布局决策

Flexbox 还是 Grid?一个简单的判断标准就够了。

决策树

一维排列(导航栏、居中)→ Flexbox。二维网格(页面结构、仪表盘)→ Grid。

场景速查

六种常见场景的推荐方案和核心代码 — 遇到布局问题时直接查表。

布局决策树

问自己:我需要控制行还是列,还是两个都要?

默认文档流——元素天然从上到下排列,无需额外布局就能用。
一维(单方向)→ Flexbox
导航栏、按钮组、居中对齐、等高列:只需要控制一行或一列的排布。
二维(行 + 列)→ Grid
页面结构、仪表盘、复杂布局:行和列都要精确控制。
二维且需响应式 → Grid + minmax + auto-fit
图片墙、产品列表:列数随容器宽度自动伸缩。
一句话总结:一维排列用 Flexbox,二维网格用 Grid。实际项目中两者经常混用——外层 Grid 控制页面结构,内层 Flexbox 处理组件内排列。

场景速查表

遇到具体场景时,查这张表就够了

场景推荐方案核心代码
水平/垂直居中Flexboxdisplay:flex; justify-content:center; align-items:center;
导航栏Flexboxdisplay:flex; justify-content:space-between;
页面整体结构Gridgrid-template-areas: "header header" "sidebar main";
响应式卡片列表Gridrepeat(auto-fit, minmax(250px, 1fr))
等高列Flexboxdisplay:flex; align-items:stretch;
复杂仪表盘Gridrepeat(4, 1fr) + 跨行跨列

动手练习

Flexbox 练习

  • 创建带图标的导航栏,图标与文字垂直居中
  • 实现三栏布局:中间固定宽度,两侧弹性
  • 用 Flexbox 实现水平垂直居中的登录表单

Grid 练习

  • 用 Grid 创建 8x8 棋盘
  • 实现响应式博客布局(侧边栏 + 主内容)
  • 创建包含跨行列组件的仪表盘

综合练习

  • 分析电商首页:哪些用 Flexbox,哪些用 Grid
  • 将 float 布局的页面重构为 Flexbox/Grid
  • 创建完全响应式的个人作品集页面

本章学习完毕

CSS 布局技术已经从"如何实现"发展到"如何优雅实现"。掌握 Flexbox 和 Grid,用更少的代码、更高的效率构建现代网页。

下一章:CSS3 响应式设计 →

1 / 25