Veloris.
返回索引
概念基础 2026-03-08

CSS 布局体系:Flexbox 与 Grid——一维和二维的分工协作

5 分钟
1.4k words

CSS 布局体系:Flexbox 与 Grid——一维和二维的分工协作

前言

上一篇我们学了盒模型,知道了每个元素是一个矩形盒子。但问题来了:这些盒子怎么排列?水平并排?垂直居中?两栏布局?响应式网格?

CSS 布局方案经历了从 floatpositionFlexboxGrid 的演进。现代开发中,Flexbox 和 Grid 是绝对主力,float 基本退居二线。

两者的核心区别很简单:Flex 管一条线(一维),Grid 管一张表(二维)。这篇文章会带你掌握两者的核心用法,并在最后告诉你什么时候用哪个。

本文篇幅较长,建议边看边在浏览器中动手试。Chrome DevTools 内置了 Flex 和 Grid 的可视化调试工具,在 Elements 面板中选中 Flex/Grid 容器时会自动显示辅助线。

正文

1. display 属性:布局的起点

在学 Flex 和 Grid 之前,先理解 display 属性——它决定元素的布局行为:

display: block;        /* 块级:独占一行(div, p, h1 的默认值) */
display: inline;       /* 行内:与其他元素同行(span, a 的默认值) */
display: inline-block; /* 行内块:同行但可设宽高(img 的行为) */
display: none;         /* 隐藏元素(不占空间) */
display: flex;         /* ⭐ 弹性盒子布局 */
display: grid;         /* ⭐ 网格布局 */

2. Flexbox 弹性盒子布局

Flexbox 是一维布局模型——在一条轴线上排列子元素(水平或垂直)。

2.1 核心概念

主轴方向(默认水平 →)
─────────────────────────────────►
┌──────────────────────────────────┐  ▲
│  ┌──────┐  ┌──────┐  ┌──────┐   │  │
│  │ item │  │ item │  │ item │   │  │ 交叉轴
│  │  1   │  │  2   │  │  3   │   │  │ (垂直)
│  └──────┘  └──────┘  └──────┘   │  │
└──────────────────────────────────┘  ▼
              flex container
  • Flex 容器(container):设置 display: flex 的父元素
  • Flex 项目(item):容器的直接子元素
  • 主轴(main axis):项目排列的方向(默认水平从左到右)
  • 交叉轴(cross axis):垂直于主轴的方向

2.2 容器属性

.container {
  display: flex;

  /* 1. 主轴方向 */
  flex-direction: row;            /* 默认:水平从左到右 → */
  flex-direction: row-reverse;    /* 水平从右到左 ← */
  flex-direction: column;         /* 垂直从上到下 ↓ */
  flex-direction: column-reverse; /* 垂直从下到上 ↑ */

  /* 2. 是否换行 */
  flex-wrap: nowrap;   /* 默认:不换行(挤在一行) */
  flex-wrap: wrap;     /* 换行 */

  /* 3. 主轴对齐(分配水平方向的空间) */
  justify-content: flex-start;    /* 靠左(默认) */
  justify-content: flex-end;      /* 靠右 */
  justify-content: center;        /* 居中 */
  justify-content: space-between; /* 两端对齐,间距均分 */
  justify-content: space-around;  /* 每个元素两侧间距相等 */
  justify-content: space-evenly;  /* 所有间距完全相等 */

  /* 4. 交叉轴对齐(分配垂直方向的空间) */
  align-items: stretch;    /* 默认:拉伸填满容器高度 */
  align-items: flex-start; /* 顶部对齐 */
  align-items: flex-end;   /* 底部对齐 */
  align-items: center;     /* 垂直居中 */
  align-items: baseline;   /* 文字基线对齐 */

  /* 5. 多行时交叉轴对齐 */
  align-content: flex-start;
  align-content: center;
  align-content: space-between;

  /* 6. 项目之间的间距(推荐用 gap 代替 margin) */
  gap: 16px;          /* 行列间距相同 */
  gap: 16px 24px;     /* 行间距 列间距 */
}

2.3 项目属性

.item {
  /* 1. 放大比例(默认 0,不放大) */
  flex-grow: 1;    /* 等分剩余空间 */

  /* 2. 缩小比例(默认 1,空间不足时等比缩小) */
  flex-shrink: 0;  /* 不缩小 */

  /* 3. 基础尺寸 */
  flex-basis: 200px; /* 类似 width,但更灵活 */

  /* 简写(最常用) */
  flex: 1;           /* flex-grow:1, flex-shrink:1, flex-basis:0% */
  flex: 0 0 300px;   /* 不放大、不缩小、固定 300px */

  /* 4. 单个项目的交叉轴对齐(覆盖容器的 align-items) */
  align-self: center;

  /* 5. 排序 */
  order: -1;  /* 数值越小排越前,默认 0 */
}

2.4 Flex 经典布局实战

💡 工程师手记:CSS 居中曾是前端面试的经典难题——垂直居中尤其折磨人,需要各种 hack。Flexbox 用两行代码终结了这个噩梦。这大概是我学前端时最有”时代进步”感触的一刻。

(建议替换为你自己学 Flexbox 时的真实感受)

水平垂直居中(最经典的用法):

.center-box {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  height: 100vh;
}

导航栏

.navbar {
  display: flex;
  justify-content: space-between; /* logo 在左,菜单在右 */
  align-items: center;
  padding: 0 24px;
  height: 60px;
}

圣杯布局(header + 三栏 + footer):

.layout { display: flex; flex-direction: column; min-height: 100vh; }
.header { height: 60px; }
.main   { display: flex; flex: 1; }
.sidebar { width: 250px; flex-shrink: 0; }
.content { flex: 1; }
.footer  { height: 80px; }
<div class="layout">
  <header class="header">头部</header>
  <div class="main">
    <aside class="sidebar">侧边栏</aside>
    <main class="content">主内容</main>
  </div>
  <footer class="footer">底部</footer>
</div>

等宽卡片列表

.card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.card {
  flex: 1 1 300px; /* 最小 300px,自动放大填满,换行 */
}

3. Grid 网格布局

Grid 是二维布局模型——同时控制行和列,适合复杂的页面布局。

3.1 核心概念

     列1        列2        列3
  ┌─────────┬─────────┬─────────┐
  │  cell   │  cell   │  cell   │  行1
  │ (1,1)   │ (1,2)   │ (1,3)   │
  ├─────────┼─────────┼─────────┤
  │  cell   │  cell   │  cell   │  行2
  │ (2,1)   │ (2,2)   │ (2,3)   │
  └─────────┴─────────┴─────────┘
  
  线(line):分隔行/列的线,从 1 开始编号
  轨道(track):两条线之间的空间(即一行或一列)
  单元格(cell):行与列交叉形成的区域
  区域(area):一个或多个单元格组成的矩形区域

3.2 容器属性

.grid-container {
  display: grid;

  /* 1. 定义列 */
  grid-template-columns: 200px 1fr 200px;     /* 三列:固定-弹性-固定 */
  grid-template-columns: repeat(3, 1fr);       /* 三列等宽 */
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* 响应式 */

  /* 2. 定义行 */
  grid-template-rows: 60px 1fr auto;           /* 固定头-弹性中-自适应尾 */

  /* 3. 间距 */
  gap: 16px;
  gap: 16px 24px;  /* 行间距 列间距 */

  /* 4. 区域命名布局(非常直观) */
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";

  /* 5. 对齐(与 Flex 类似) */
  justify-items: center;   /* 单元格内水平对齐 */
  align-items: center;     /* 单元格内垂直对齐 */
  justify-content: center; /* 整个网格在容器内水平对齐 */
  align-content: center;   /* 整个网格在容器内垂直对齐 */
}

3.3 fr 单位

fr(fraction)是 Grid 专用的弹性单位,表示”剩余空间的份数”:

grid-template-columns: 1fr 2fr 1fr;
/* 三列按 1:2:1 分配空间 */
/* 如果容器 800px,间距 0:200px + 400px + 200px */

grid-template-columns: 200px 1fr;
/* 左列固定 200px,右列占满剩余空间 */

类比fr 类似 Flex 的 flex-grow——按比例分配剩余空间。

3.4 项目属性

.grid-item {
  /* 通过网格线定位 */
  grid-column: 1 / 3;      /* 从第1条列线到第3条列线(跨2列) */
  grid-row: 1 / 2;          /* 第1行 */

  /* 简写 */
  grid-column: span 2;      /* 跨2列 */
  grid-row: span 3;         /* 跨3行 */

  /* 使用区域名(配合 grid-template-areas) */
  grid-area: header;
}

3.5 Grid 经典布局实战

经典页面布局(区域命名法):

.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr 80px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
  gap: 0;
}

.header  { grid-area: header;  background: #1a1a2e; color: white; }
.sidebar { grid-area: sidebar; background: #f0f0f0; }
.main    { grid-area: main;    padding: 24px; }
.footer  { grid-area: footer;  background: #333; color: white; }

响应式卡片网格

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
  padding: 24px;
}

auto-fill + minmax() 是响应式布局的利器:卡片最小 280px,自动填充列数,剩余空间平分。

💡 工程师手记:第一次看到 grid-template-areas 用字符串”画”布局图时,我的反应是:这也太直观了吧?HTML 定义结构,CSS 里直接”画”出布局——这比 FPGA 的约束文件直观多了。

(建议替换为你自己第一次使用 Grid areas 的感受)

12 列栅格系统

.grid-12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 24px;
}
.col-6 { grid-column: span 6; }  /* 占半行 */
.col-4 { grid-column: span 4; }  /* 占 1/3 */
.col-3 { grid-column: span 3; }  /* 占 1/4 */
.col-12 { grid-column: span 12; } /* 占满一行 */

4. ★ Flexbox vs Grid:什么时候用哪个?

这是本文的核心问题。先看一个简单的判断流程:

你要控制的是一行/一列中的排列? → Flex
你要同时控制行和列的对齐?     → Grid
不确定?                         → 先用 Flex,发现不够用再换 Grid

具体场景对照:

场景推荐原因
一行内多个元素排列Flex一维布局更简单
导航栏、按钮组Flex线性排列
水平垂直居中Flex两行代码搞定
复杂页面整体布局Grid二维控制更精确
卡片网格、响应式列表Gridauto-fill + minmax 很强大
表单对齐Grid标签和输入框完美对齐

经验法则组件内部用 Flex,页面布局用 Grid。两者经常搭配使用,不是二选一。比如:页面整体用 Grid 定义 header/sidebar/main/footer 的位置,而 navbar 内部的菜单项用 Flex 排列。

💡 工程师手记:我的经验是:不确定用哪个时先用 Flex。Flex 更简单、更直觉,90% 的场景都能应付。只有当你发现自己在用 Flex 嵌套 Flex 来模拟网格布局时,才需要换成 Grid。

(建议替换为你自己的布局选型经验)

5. position 定位(补充)

虽然 Flex/Grid 解决了大部分布局需求,但 position 在特定场景仍然必不可少:

position: static;   /* 默认,按文档流排列 */
position: relative; /* 相对定位:相对于自身原位置偏移,不脱离文档流 */
position: absolute; /* 绝对定位:相对于最近的 relative/absolute 祖先定位 */
position: fixed;    /* 固定定位:相对于浏览器窗口,滚动不动(如固定导航栏) */
position: sticky;   /* 粘性定位:滚动到指定位置后"粘住" */

常用组合——父 relative 子 absolute

.card {
  position: relative;
}
.badge {
  position: absolute;
  top: -8px;
  right: -8px;
  /* 标记定位在卡片右上角 */
}

固定导航栏:

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;  /* 确保在其他元素上面 */
}

常见问题

💬 你可能会问:justify-content 和 align-items 怎么记?总是混淆。

简单记法:justify 管主轴方向(默认水平),align 管交叉轴方向(默认垂直)。如果你用 flex-direction: column 把主轴变成垂直,它们的作用方向也跟着交换。

💬 你可能会问:float 布局还需要学吗?

现在基本不需要了。float 最初是为了实现”图片环绕文字”的效果,后来被拿来做布局是因为没有更好的工具。现在有了 Flex 和 Grid,float 可以安心退休了。

💬 你可能会问:Grid 的浏览器兼容性怎么样?

2026 年,所有现代浏览器(Chrome、Firefox、Safari、Edge)都完全支持 Flex 和 Grid。除非你要兼容 IE 11(已经停止支持),否则放心用。

总结

知识点核心要点
displayflex(一维布局)和 grid(二维布局)是现代主力
Flexbox容器:justify-content 控制主轴,align-items 控制交叉轴
Flex 项目flex: 1 等分空间,flex: 0 0 Xpx 固定尺寸
Gridgrid-template-columns/rows 定义网格,fr 分配弹性空间
Grid 区域grid-template-areas 用名称直观定义布局
响应式网格repeat(auto-fill, minmax(Xpx, 1fr)) 是万能公式
选型策略组件内部 Flex,页面布局 Grid,可混合使用
positionfixed 固定定位、sticky 粘性定位、父 relativeabsolute

下一步行动:强烈推荐玩一遍 Flexbox FroggyGrid Garden——用游戏的方式练习布局属性,比读十遍文档都有效。

参考资料


📖 系列导航:本文是「FPGA 工程师的前端学习笔记」系列的第 4 篇 上一篇:CSS 入门:选择器与盒模型 下一篇:CSS 响应式设计与媒体查询

End of file.