06Grid 网格布局

Flex 管「一条线」,Grid 管「一张网」:行和列同时定义, 子项一个个放进格子里——二维布局的终极答案。 整页骨架、相册、仪表盘,从此不用任何 hack。

约 25 分钟 10 个动手实验 二维布局终极答案

一、Flex vs Grid:怎么选

两个都是现代布局主力,维度不同、分工不同。先用一张表建立全局观, 之后写页面先问自己一句:我是在排一条线,还是在铺一张网?

Flex 与 Grid 的定位对比
对比项Flex 弹性盒Grid 网格
维度一维(一行或一列)二维(行 + 列)
思维从「内容」出发,排队伸缩从「容器」出发,先画格子再放东西
子项位置沿主轴依次排,不看行也不看列可以指定「第几行第几列」「跨几格」
适合导航栏、按钮组、一行卡片、垂直居中整页骨架、相册、日历、仪表盘
能混用吗完美配合:Grid 排大框架,每个格子里再用 Flex 排细节
一个判断技巧:内容决定结构 → Flex;结构决定内容 → Grid。 比如「一组标签,多长都排一行」是内容说了算,用 Flex; 「七列的日历、头身脚的页面」是格子说了算,用 Grid。

二、display: grid 与网格基本概念

在容器上写 display: grid,它就成了网格容器, 直接子元素成为网格项目。先用几个术语把地图画清楚:

  • 轨道(track):一行或一列的统称,由 grid-template-columns / grid-template-rows 定义;
  • 单元格(cell):行和列交叉出的小格子;
  • 网格线(grid line):格子的边线,编号从 1 开始——竖线从左往右数,横线从上往下数,第 4 节定位全靠它;
  • 网格区域(area):由若干格子拼成的大块,可以命名(第 5 节)。

只定义列、不指定位置时,项目会自动摆放:从左到右、放满一行换下一行,跟流水线一样。

上面行高自动、下面 grid-template-rows 写死两行高度:把下面舞台的 grid-template-rows 删掉,两行立刻变回内容撑开
和 Flex 一样:grid 只管直接子元素;子元素的 float / clear / vertical-align 同样失效。 另外 display: inline-grid 可以让网格容器本身行内化,道理同 inline-flex。

三、轨道尺寸六种写法

grid-template-columns 的每一列,都能用不同单位描述。这六种写法覆盖了 99% 的场景:

轨道尺寸取值分析
写法含义典型用途
90px固定 90 像素,多一分不少固定侧栏、图标列
50%容器宽度的 50%简单两栏
1fr可用空间切成几份,占一份等宽 / 按比例分栏
auto按内容自适应宽窄「这一列包住内容就行」
minmax(100px, 1fr)最小 100px、最大 1fr 的弹性范围防压坏内容
repeat(3, 1fr)1fr 1fr 1fr 写三遍的简写等分多列
五种列定义对比:把 .fr1fr 2fr 1fr 改成 1fr 1fr 1fr,中间的 2fr 立刻变细
fr = fraction(份数),思路和 Flex 的 grow 一样: 先扣掉固定尺寸的列和 gap,剩下的空间再按份数切。 所以 200px 1fr 1fr 的意思是「先留 200px,剩下一人一半」。

四、网格线定位:grid-column / grid-row

Grid 最强大的地方:想让某个项目「从第 1 条竖线到第 3 条竖线、从第 1 条横线到第 3 条横线」,直接写。 语法是 起始线 / 结束线,编号从 1 开始;也可以用 span n 表示「从当前位置跨 n 格」。

hero 用线编号占了 2×2 大格:把 .herogrid-column: 1 / 3 改成 1 / 2,它立刻缩回一列宽
wide 横跨 2 列、tall 纵跨 2 行:把 .widegrid-column: span 2 改成 span 3,它立刻占满整行
数线规则:3 列网格有 4 条竖线,编号 1~4;grid-column: 1 / 3grid-column: span 2 在起点恰好是 1 时结果相同,起点不同就不同。 另外「结束线 = 起始线 + 跨越数」,想不通就在纸上画格子。

五、命名区域:grid-template-areas

逐个数线太累?把布局画成 ASCII 图直接写进 CSS: grid-template-areas 用字符串描述每一行,每个名字是一块区域, 项目再用 grid-area: 名字 报到。整页骨架的首选写法。

template-areas 搭的页面骨架:把 "nv mn""ft ft" 两行顺序对调,页面立刻上下翻过来
「ASCII 布局图」直接翻译成 CSS——这就是 template-areas 的魅力: 结构一目了然,改布局只动几行字符串。规则只有两条:每行的格子数要相同; 想留空写个句点 .(如 "hd hd" ". mn")。

六、隐式轨道与自动流:grid-auto-rows / grid-auto-flow

项目比定义的格子多怎么办?Grid 会自动补轨道(叫隐式轨道): 行方向默认按内容高、列方向默认按内容宽。grid-auto-rows / grid-auto-columns 就是给这些「计划外轨道」定尺寸的;grid-auto-flow 则决定自动摆放的方向。

grid-auto-* / grid-auto-flow 取值说明
属性含义关键点
grid-auto-rows隐式行的高度项目超出定义行时自动补高
grid-auto-columns隐式列的宽度同理,补列时生效
grid-auto-flowrow(默认)按行填 / column 按列填 / row dense · column dense 回头填坑dense 会把前面空的小格塞满
上面 7 个项目挤 3 列、行高统一 44px:把 grid-auto-rows 改成 30px,多出的行立刻变矮
「图片高度不一的瀑布流」常用 grid-auto-rows: 10px + 每张图 grid-row: span n 的组合控制精确行数;另有取值 dense (写成 grid-auto-flow: row dense)会让浏览器「回头填坑」,把前面留下的小空格塞满。

七、对齐全家桶:items 管格子内,content 管整张网

Grid 的对齐比 Flex 多一层——因为它有两层空间:项目在「单元格内」的位置, 以及「整张网格」在容器里的位置。记住两条名字规律就不混:

  • justify-items / align-items —— 项目在自己的格子里怎么摆(水平 / 垂直);
  • justify-content / align-content —— 整张网格在容器里怎么摆(轨道有剩余空间时才看得出效果);
  • place-items / place-content —— 上面两个的「竖写简写」:place-items: 垂直 水平
Grid 对齐六兄弟(名称规律)
作用层次水平垂直竖写简写
项目在格子内justify-itemsalign-itemsplace-items
整张网格在容器内justify-contentalign-contentplace-content
单个项目覆盖justify-selfalign-self
项目在各自 72px 高的格子里对齐:把 .placeplace-items: center 改成 place-items: end end,文字立刻滑到右下角
整张网格(虚线框内的格子组)在容器里的三种摆法:把 .p3align-content: end 改成 start,它立刻弹回顶部
项目级也有对应的 justify-self / align-self(覆盖容器设置),和 Flex 的 align-self 同理。 默认值都是 stretch:所以 Grid 项目不写宽高时,默认就撑满整个格子

八、经典实战:响应式卡片墙与日历

两个 Grid 招牌菜。卡片墙的精髓是 repeat(auto-fill, minmax(108px, 1fr)): 「每列至少 108px,能塞几列塞几列,剩下的空间平分」——零媒体查询的响应式

商品卡片墙:把 minmax(108px, 1fr) 里的 108px 改成 180px,一行能放的卡片立刻变少
日历网格:把 .firstgrid-column: 5 改成 2,整个月立刻从周二开头
auto-fill 与 auto-fit 的微妙差别:两者都是「能塞几列塞几列」; 区别在项目不够多时——auto-fill 会保留空列占位,auto-fit 把空列收掉、让现有列拉伸铺满。 卡片墙一般用 auto-fill,数量少还想铺满就用 auto-fit。

九、Grid 属性速查表

把整章用到的容器与项目属性归拢到两张表,之后写 Grid 忘哪个查哪个。

Grid 容器属性速查
属性作用常见取值
grid-template-columns定义列轨道px / % / fr / auto / minmax() / repeat()
grid-template-rows定义行轨道同上
grid-template-areas用 ASCII 图命名区域「hd hd」…+ 句点表示空
grid-auto-rows隐式行高度如 44px
grid-auto-columns隐式列宽度长度值
grid-auto-flow自动摆放方向row / column / dense
gap行列间距row-gap / column-gap 分开设
justify-items / align-items项目在格子内对齐start / center / end / stretch
justify-content / align-content整张网格在容器内对齐+ space-between 等
place-items / place-content上面两组竖写简写place-items: 垂直 水平
Grid 项目属性速查
属性作用取值
grid-column水平定位(线号 / span)1 / 3 · span 2
grid-row垂直定位(线号 / span)1 / 3 · span 2
grid-area抱一个命名区域区域名 / 四项线号缩写
justify-self / align-self覆盖容器的格子内对齐start / center / end / stretch

十、本章小结 · 布局模块收官

至此,六种布局手段全部到手:文档流 → 浮动(读懂老代码)→ 定位(叠放钉住)→ 溢出(收拾残局)→ Flex(一维排队)→ Grid(二维铺格)。 实战中 90% 的页面 = Grid / Flex 搭框架 + 定位做点缀:

  • 整页骨架:grid-template-areas 画头 / 身 / 脚、边栏 + 主区;
  • 格子内部:导航、按钮组、卡片行交给 Flex;
  • 点睛之笔:角标、吸顶、弹层交给定位;
  • 长内容:省略号、滚动区交给 overflow。
毕业自测:用 Grid areas 画出「header / 左侧 nav / 主区 / footer」骨架, 主区里用 repeat(auto-fill, minmax(…)) 铺一排响应式商品卡, 卡片内部价格和销量用 Flex 两端对齐,卡片右上角再用定位加一个「热销」角标。 四种手段各就各位,布局模块就真正毕业了。