Flex 与 Grid 布局完全指南

一篇讲透 display: flexdisplay: grid:从基本概念到每一个属性,全部附代码示例与效果说明,最后给出两者的对比与选型建议。


项目示例预览地址

codepen.io/editor/wang...

一、Flex 弹性布局

1.1 基本概念

Flex 是"一维"布局,只处理一个方向(主轴)上的排列。

css 复制代码
.container {
  display: flex; /* 或 inline-flex */
}

关键概念:

  • 主轴(main axis) :由 flex-direction 决定,默认水平(row),项目沿主轴排列;
  • 交叉轴(cross axis):与主轴垂直的方向;
  • 主起/主尾、交叉起/交叉尾:主轴和交叉轴的起点与终点;
  • 容器(flex container) :设置 display: flex 的元素;
  • 项目(flex item):容器的直接子元素。
ini 复制代码
主轴方向(flex-direction: row)
┌──────────────────────────────────────┐
│  [item1]  [item2]  [item3]  [item4]  │ ← 项目沿主轴排列
│                                      │
│                                      │ ← 交叉轴方向(垂直)
└──────────────────────────────────────┘

示例

html 复制代码
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
css 复制代码
.container {
  display: flex;
  background: #f0f4ff;
  padding: 16px;
}
.item {
  background: #409eff;
  color: #fff;
  width: 80px;
  height: 80px;
  margin: 8px;
  display: flex;
  justify-content: center;
  align-items: center;
}

1.2 容器属性(写在父元素上)

① flex-direction ------ 主轴方向

取值 效果
row(默认) 水平从左到右
row-reverse 水平从右到左
column 垂直从上到下
column-reverse 垂直从下到上
css 复制代码
.container { flex-direction: row; }      /* 默认:→ → → */
.container { flex-direction: row-reverse; } /* ← ← ← */
.container { flex-direction: column; }   /* 竖排:↓↓↓ */
.container { flex-direction: column-reverse; } /* ↑↑↑ */

注意:row-reverse/column-reverse 不只是换方向,主轴的起点终点也互换,justify-content 的对齐起点会跟着变。

② flex-wrap ------ 是否换行

取值 效果
nowrap(默认) 不换行,空间不足时项目被压缩
wrap 换行,多行排列
wrap-reverse 换行,且新行从交叉轴反向开始
css 复制代码
.container { flex-wrap: wrap; }   /* 放不下就换到下一行 */
.container { flex-wrap: nowrap; } /* 默认,强行塞一行 */
.container { flex-wrap: wrap-reverse; } /* 换行且反向 */

③ flex-flow ------ flex-direction + flex-wrap 简写

css 复制代码
.container {
  /* flex-direction: row; flex-wrap: wrap; */
  flex-flow: row wrap;
}

④ justify-content ------ 主轴方向的对齐

取值 效果
flex-start(默认) 靠主起点
flex-end 靠主终点
center 居中
space-between 两端对齐,项目间间距相等
space-around 每项两侧有相等的空间
space-evenly 所有间隙完全相等
css 复制代码
.container {
  display: flex;
  justify-content: space-between; /* 典型:导航栏左右分布 */
}
ini 复制代码
justify-content: space-between
[item1]          [item2]          [item3]

justify-content: space-evenly
   [item1]    [item2]    [item3]

⑤ align-items ------ 交叉轴方向的对齐(单行)

取值 效果
stretch(默认) 拉伸填满交叉轴高度
flex-start 靠交叉起点
flex-end 靠交叉终点
center 交叉轴居中
baseline 按文字基线对齐
css 复制代码
.container {
  display: flex;
  align-items: center; /* 最常用:垂直居中 */
}

经典实现水平垂直居中justify-content: center; align-items: center;

⑥ align-content ------ 多行时交叉轴的对齐

flex-wrap: wrap 产生多行时才生效,取值同 justify-content(外加 stretch)。

css 复制代码
.container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between; /* 多行整体在交叉轴分布 */
  height: 400px;
}

区别:align-items 控制"每一行内项目"的对齐;align-content 控制"多行整体"的分布。单行时 align-content 无效。

⑦ gap ------ 项目间距

css 复制代码
.container {
  display: flex;
  gap: 16px;            /* 行、列间距都是 16px */
  row-gap: 12px;        /* 行间距 */
  column-gap: 8px;      /* 列间距 */
}

gapmargin 更好用:不影响两端、不会把间距算进 flex-basis


1.3 项目属性(写在子元素上)

① order ------ 排列顺序

数值越小越靠前,默认 0,可为负数。

css 复制代码
.item-1 { order: 3; }
.item-2 { order: 1; }
.item-3 { order: 2; }
/* 显示顺序:item-2 → item-3 → item-1 */

② flex-grow ------ 放大比例

默认 0(不放大)。当容器有剩余空间时,按比例分配。

css 复制代码
.container { display: flex; width: 600px; }
.item { flex-grow: 1; }   /* 平均分剩余空间 */
.item-big { flex-grow: 2; } /* 占比是别的项目的 2 倍 */
css 复制代码
剩余空间 300px
[ A:flex-grow 1 ][ B:flex-grow 2 ]  → A 分 100px,B 分 200px

③ flex-shrink ------ 缩小比例

默认 1(空间不足时允许缩小)。设为 0 则不缩小(保持原尺寸,可能溢出)。

css 复制代码
.item { flex-shrink: 0; }  /* 不缩小,宽度固定 */
.item { flex-shrink: 2; }  /* 空间不足时缩小的程度更大 */

④ flex-basis ------ 初始主轴尺寸

项目在"放大/缩小之前"的基准尺寸,默认 auto(取自身 width/height)。

css 复制代码
.item { flex-basis: 200px; } /* 先按 200px 算,再参与 grow/shrink */
.item { flex-basis: 50%; }

⑤ flex ------ flex-grow flex-shrink flex-basis 简写

写法 等价 含义
flex: 1 1 1 0% 等分剩余空间(最常用)
flex: auto 1 1 auto 按内容大小 + 参与伸缩
flex: none 0 0 auto 固定尺寸,不伸缩
flex: 0 1 auto 默认 可缩小不可放大
css 复制代码
.sidebar { flex: 0 0 240px; } /* 固定 240px,不放大不缩小 */
.main { flex: 1; }            /* 占满剩余空间 */
/* 经典:侧边栏固定 + 主区自适应 */

⑥ align-self ------ 单个项目在交叉轴的对齐

覆盖容器的 align-items,取值相同。

css 复制代码
.container { align-items: center; }
.item-special { align-self: flex-end; } /* 只把这个项目放到底部 */

Flex 属性速查表

属性 作用于 常用取值
flex-direction 容器 row / column / ...reverse
flex-wrap 容器 nowrap / wrap
flex-flow 容器 direction + wrap
justify-content 容器 center / space-between / space-evenly
align-items 容器 center / stretch / baseline
align-content 容器 多行分布
gap 容器 间距
order 项目 排列顺序
flex-grow 项目 放大比例
flex-shrink 项目 缩小比例
flex-basis 项目 初始尺寸
flex 项目 三合一简写
align-self 项目 单项目对齐

二、CSS Grid 网格布局

2.1 基本概念

Grid 是"二维"布局,同时处理行和列

css 复制代码
.container {
  display: grid; /* 或 inline-grid */
}

关键概念:

  • 网格线(grid line):划分网格的线,行线/列线;
  • 网格轨道(track):两条相邻线之间的行/列;
  • 网格单元(cell):行与列交叉的最小单位;
  • 网格区域(area):一个或多个单元格组成的矩形区域。
makefile 复制代码
列线: 1        2       3        4
      │  100px │ 1fr   │ 1fr    │
行线 1┌────────┬────────┬────────┐
     │  cell  │  cell  │  cell  │
行线 2├────────┼────────┼────────┤
     │  cell  │  cell  │  cell  │
行线 3└────────┴────────┴────────┘

示例

html 复制代码
<div class="grid">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
</div>
css 复制代码
.grid {
  display: grid;
  grid-template-columns: 100px 1fr 1fr; /* 3 列:固定 + 两列自适应 */
  grid-template-rows: 80px 80px;        /* 2 行 */
  gap: 12px;
}
.box {
  background: #409eff;
  color: #fff;
  display: grid;
  place-items: center; /* 单元格内居中 */
}

2.2 容器属性(写在父元素上)

① grid-template-columns / grid-template-rows ------ 定义轨道

支持多种单位:

css 复制代码
/* 固定值 */
.grid { grid-template-columns: 100px 200px 100px; }

/* 百分比 */
.grid { grid-template-columns: 25% 25% 50%; }

/* fr(fraction 分数单位):按比例瓜分剩余空间 */
.grid { grid-template-columns: 1fr 2fr 1fr; } /* 1:2:1 三列 */

/* repeat():重复 */
.grid { grid-template-columns: repeat(3, 1fr); } /* 等同 1fr 1fr 1fr */

/* minmax():最小-最大约束 */
.grid { grid-template-columns: minmax(200px, 1fr) 1fr; }
/* 第一列至少 200px,最多占满剩余 */

/* auto:按内容 */
.grid { grid-template-columns: auto 1fr; }
css 复制代码
/* 行同理 */
.grid {
  grid-template-rows: 100px auto 1fr; /* 头 / 内容自适应 / 尾部占满 */
}

auto-fill 与 auto-fit ------ 自动填充

css 复制代码
.grid {
  display: grid;
  /* 每列至少 200px,能放几列放几列(自适应列数) */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  /* auto-fit 与 auto-fill 区别:项目少时 auto-fit 会把空轨道塌陷合并 */
}

② grid-template-areas ------ 区域命名布局

css 复制代码
.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 60px 1fr 60px;
  grid-template-areas:
    "header header"
    "sidebar content"
    "footer footer";
}
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer  { grid-area: footer; }
css 复制代码
┌──────────┬──────────┐
│ header   │ header   │
├──────────┼──────────┤
│ sidebar  │ content  │
├──────────┼──────────┤
│ footer   │ footer   │
└──────────┴──────────┘

.(点)表示空单元格:grid-template-areas: "a . b";

③ gap ------ 行列间距

css 复制代码
.grid {
  display: grid;
  gap: 16px;          /* 行列统一 */
  row-gap: 12px;      /* 行间距 */
  column-gap: 8px;    /* 列间距 */
}

④ grid-auto-flow ------ 项目自动放置规则

取值 效果
row(默认) 按行依次放置,放满一行换下一行
column 按列依次放置
dense 回填前面留下的空洞(可与 row/column 组合:row dense
css 复制代码
.grid { grid-auto-flow: column; }  /* 纵向排列 */
.grid { grid-auto-flow: row dense; } /* 尽量紧凑,回填空洞 */

⑤ grid-auto-rows / grid-auto-columns ------ 隐式轨道大小

显式轨道用 grid-template-* 定义;放不下的项目会创建"隐式轨道",用这组属性控制其大小。

css 复制代码
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 80px;           /* 新增行的默认高度 */
  grid-auto-columns: 100px;       /* 新增列的默认宽度 */
}

⑥ justify-items / align-items ------ 项目在单元格内的对齐

取值 效果
stretch(默认) 拉伸填满单元格
start 起点(左/上)
end 终点(右/下)
center 居中
css 复制代码
.grid {
  justify-items: center;  /* 水平居中 */
  align-items: center;    /* 垂直居中 */
  /* 简写 */
  place-items: center;    /* = justify-items + align-items */
}

⑦ justify-content / align-content ------ 整个网格在容器内的对齐

当网格总尺寸小于容器(例如用固定像素定义轨道)时生效。

css 复制代码
.grid {
  display: grid;
  grid-template-columns: 100px 100px; /* 总宽 200px < 容器 */
  justify-content: center;   /* 网格整体水平居中 */
  align-content: space-between; /* 网格整体垂直分布 */
  /* 简写 */
  place-content: center;
}

取值:start / end / center / stretch / space-between / space-around / space-evenly

⑧ grid-template ------ 简写

css 复制代码
.grid {
  /* grid-template-rows / grid-template-columns / grid-template-areas */
  grid-template:
    "header header" 60px
    "sidebar content" 1fr
    "footer footer" 60px
    / 200px 1fr;
}

2.3 项目属性(写在子元素上)

① grid-column / grid-row ------ 按网格线定位

css 复制代码
.item {
  /* 从第 1 列线到第 3 列线(占 2 列) */
  grid-column: 1 / 3;
  /* 从第 2 行线开始,跨越 2 行 */
  grid-row: 2 / span 2;
}

常用写法:

css 复制代码
.item { grid-column: 1 / 3; }      /* 起线 / 止线 */
.item { grid-column: 1 / -1; }     /* -1 表示最后一条线,即占满整行 */
.item { grid-column: span 2; }     /* 跨越 2 列(不指定起线) */
.item { grid-column: 2; }          /* 单列简写 */
.item { grid-column: 1 / span 2; } /* 从线 1 开始跨 2 列 */

示例:一列跨两列

css 复制代码
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.item-wide { grid-column: 1 / 3; } /* 占第 1、2 列 */

② grid-area ------ 区域定位

两种用法:用 grid-template-areas 定义的名字,或四线定位。

css 复制代码
/* 用法一:区域名(配合 grid-template-areas) */
.item { grid-area: sidebar; }

/* 用法二:四条网格线 row-start / column-start / row-end / column-end */
.item {
  grid-area: 1 / 1 / 3 / 3;
  /* 从第1行第1列 到 第3行第3列(占 2x2) */
}

③ justify-self / align-self / place-self ------ 单个项目在单元格内对齐

css 复制代码
.item {
  justify-self: center; /* 水平居中(覆盖 justify-items) */
  align-self: end;      /* 垂直靠下 */
  place-self: center;   /* 简写,单元格内居中 */
}

Grid 属性速查表

属性 作用于 作用
grid-template-columns/rows 容器 定义轨道(fr / repeat / minmax)
grid-template-areas 容器 区域命名布局
gap 容器 行列间距
grid-auto-flow 容器 自动放置规则(row/column/dense)
grid-auto-rows/columns 容器 隐式轨道大小
justify/align/place-items 容器 项目在单元格内对齐
justify/align/place-content 容器 网格整体对齐
grid-column/row 项目 按线定位、跨越
grid-area 项目 区域定位 / 四线定位
justify/align/place-self 项目 单项目对齐

三、Flex vs Grid:对比与选型

3.1 核心区别

对比项 Flex Grid
维度 一维(一个方向) 二维(行 + 列)
设计思想 内容驱动(项目伸缩填满) 布局驱动(先画网格再放内容)
擅长 单行/单列排列、对齐、居中等 页面骨架、规则二维布局
跨行跨列 不支持(同一轴线) 原生支持(span / grid-area)
列数 由内容决定 由轨道定义决定

3.2 典型选型建议

优先用 Flex

css 复制代码
/* 导航栏:一行水平分布 */
.nav { display: flex; justify-content: space-between; align-items: center; }

/* 按钮组 / 图标行 */
.toolbar { display: flex; gap: 8px; }

/* 垂直居中 */
.center { display: flex; justify-content: center; align-items: center; }

/* 固定侧栏 + 自适应主区 */
.sidebar { flex: 0 0 240px; }
.main { flex: 1; }

优先用 Grid

css 复制代码
/* 页面整体骨架:二维区域划分 */
.page {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar content"
    "footer footer";
}

/* 商品卡片网格:自动响应式列数 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}

/* 九宫格 / 表格类布局 */
.board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 8px;
}

3.3 两者混用(最常用实践)

Grid 做整体骨架 ,用 Flex 做局部对齐

css 复制代码
.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr;
  grid-template-areas:
    "header header"
    "sidebar content";
  height: 100vh;
}
.header {
  grid-area: header;
  display: flex;               /* Grid 里再用 Flex */
  justify-content: space-between;
  align-items: center;
}
.content {
  grid-area: content;
  display: grid;               /* 内容区再嵌套 Grid */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px;
}

3.4 常见面试追问

Q:Flex 和 Grid 能互相替代吗? 不能完全替代。Flex 擅长单维度的弹性排列与对齐;Grid 擅长二维的规则划分。复杂布局常两者组合使用。

Q:flex: 11fr 的区别?

  • flex: 1 是 flex-grow: 1,针对剩余空间按比例分配;
  • 1fr 是网格分数单位,针对整条轨道按比例分配。 两者都能实现自适应,但作用模型不同。

Q:什么时候用 place-items 什么时候用 place-content

  • place-items 控制项目在单元格内的位置;
  • place-content 控制整个网格在容器中的位置。

收藏这份指南,配合动手敲代码练习:先掌握 Flex 的一维思维,再掌握 Grid 的二维思维,两者结合基本能覆盖前端 99% 的布局场景。

相关推荐
CarIise1 天前
事件传播、CSS动画、服务器字体与jQuery
服务器·css·jquery
XLYcmy1 天前
HTML/CSS/JS 基础与 Vue 技术栈深度解析
java·前端·css·html·vue3·vue2·api
风月说与山鬼1 天前
四、Tailwind CSS——间距与尺寸
前端·css·tailwind css
风月说与山鬼1 天前
三、Tailwind CSS——排版与文字样式
前端·css·tailwind css
里欧跑得慢1 天前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
晓得迷路了1 天前
栗子前端技术周刊第 144 期 - Rspack 2.2、pnpm 12、Solid 2.0 RC...
前端·javascript·css
CarIise2 天前
下拉菜单HTML/CSS/JS实现
前端·css
里欧跑得慢3 天前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
烂蜻蜓3 天前
Flask入门教程(十):静态文件——CSS、JS与图片的正确管理方式
javascript·css·flask