跳到主要内容

CSS Grid 网格布局实战

引入段落:如果说上一章学习的 Flexbox 是为了解决“一维布局”(让元素在一行或一列中排列得更好看)而生,那么 CSS Grid(网格布局) 则是为真正的“二维布局”量身定制的终极武器。它是迄今为止 CSS 中最为强大的布局系统。通过 Grid,我们可以像在 Excel 中画表格一样,同时精确控制网页的“行(Row)”和“列(Column)”,轻松实现过去必须借助笨重的 Bootstrap 栅格系统或复杂 JavaScript 计算才能完成的响应式、不对称、甚至是重叠的页面排版。

一、Grid 与 Flexbox:竞品还是搭档?

初学者常常疑惑:既然都有 Flexbox 了,为什么还要学 Grid?我到底该用哪个?

  • 维度差异:Flexbox 擅长一维空间,你把元素扔进去,它们像水流一样填充单根轴线。Grid 擅长二维空间,你先画好横竖交叉的骨架,然后再把元素填到特定的“格子”里。
  • 控制方向:Flexbox 是“基于内容(Content-first)”的布局。容器虽然有规则,但最终长什么样很大程度上由里面的子元素大小决定。Grid 则是“基于网格(Grid-first)”的。父容器完全主宰了布局的框架,子元素只能乖乖呆在划定好的区域内。

:::tip黄金搭档法则在现代前端工程中,它们不是互斥的,而是完美搭档常见范式:使用 CSS Grid 搭建页面的宏观架构(如 头部、侧边栏、主体区、页脚),然后在主体区内部的某个卡片组件中,使用 Flexbox 安排卡片内头像和文字的水平对齐。:::

二、Grid 核心术语与坐标系

要驯服 Grid,必须熟悉它的专属词汇体系。假设我们通过 display: grid; 将一个容器分成了 3 行 3 列的网格:

  1. 网格容器 (Grid Container):应用了 display: grid 的父元素。
  2. 网格项 (Grid Item):容器内部直接包含的子元素。
  3. 网格线 (Grid Line):构成网格结构的水平和垂直的分界线。一个 3x3 的网格,有 4 条水平线(从上到下编号 1-4)和 4 条垂直线(从左到右编号 1-4)。这是 Grid 定位的灵魂。
  4. 网格轨道 (Grid Track):两条相邻网格线之间的空间。其实就是我们常说的“一行”或“一列”。
  5. 网格单元格 (Grid Cell):两条相邻行网格线和两条相邻列网格线相交的最小区域。
  6. 网格区域 (Grid Area):由四条网格线包围的总空间,可以由任意多个相邻的单元格组成一个矩形块。

三、构建网格骨架:容器属性

在父容器上,我们负责“画”出网格的结构。

3.1 划分行与列:grid-template-columns / rows

这两个属性用来定义网格中每一列的宽度和每一行的高度。

.container {
display: grid;
/* 定义三列:第一列固定 100px,第二列 200px,第三列自适应 (auto) */
grid-template-columns: 100px 200px auto;
/* 定义两行:每行固定 50px */
grid-template-rows: 50px 50px;
}

强大的 fr 单位与辅助函数

Grid 引入了全新的动态单位和函数,这是它极具弹性的秘密所在:

  • fr (Fraction, 分数):代表网格容器中可用空间的一个比例份额。
    /* 将容器划分为三列,比例为 1:2:1。第二列永远是其他两列的两倍宽 */
    grid-template-columns: 1fr 2fr 1fr;
  • repeat():当有许多大小相同的轨道时,用来简化书写。
    /* 等同于 1fr 1fr 1fr 1fr */
    grid-template-columns: repeat(4, 1fr);
  • minmax(min, max):定义一个尺寸的最小和最大边界。这在响应式设计中是无价之宝。
    /* 这一列最小不能小于 150px,如果有剩余空间,最大可以占满 1fr */
    grid-template-columns: minmax(150px, 1fr);

3.2 具象化排版:grid-template-areas

这是 Grid 中最具魔法的一个属性。它允许你通过字符串(就像画 ASCII 图一样)直接拼出页面的布局。

.container {
display: grid;
grid-template-columns: 200px 1fr 200px; /* 左中右三列 */
grid-template-rows: 60px 1fr 40px; /* 上中下三行 */

/* 给各个格子命名,相同的名字会自动合并成一个大区域! */
grid-template-areas:
'header header header'
'sidebar main ads'
'footer footer footer';
}

3.3 间距与全局对齐

  • gap:与 Flexbox 类似,统一设置网格的行列间距。gap: 20px;
  • 单元格内容对齐justify-items (水平方向) 和 align-items (垂直方向)。控制所有的网格项在其所属的格子内部如何停靠。
  • 整个网格对齐justify-contentalign-content。如果网格的整体大小小于容器的总大小,这两个属性决定网格群在容器中的位置(类似于 Flexbox,支持 center, space-between 等)。

四、摆放元素:网格项属性

骨架搭好了,接下来需要将子元素塞进这些格子里。

4.1 基于网格线定位 (Grid Lines)

这是最精确的定位方式。通过指定元素从哪条线开始,跨越到哪条线结束。

.item-1 {
/* 放置在第一行,从第1条垂直线开始,跨越到第4条垂直线结束(也就是横跨3列) */
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 1;
grid-column-end: 4;

/* 以上四行可以简写为: */
grid-row: 1 / 2;
grid-column: 1 / 4;

/* 还可以使用 span 关键字,语义更强:从第一条线开始,跨越 3 步 */
grid-column: 1 / span 3;
}

提示:允许网格项互相重叠!如果两个元素的坐标有交集,只需配合 z-index 即可实现精美的图片/文字堆叠设计,无需绝对定位。

4.2 基于命名区域定位 (Grid Areas)

配合容器的 grid-template-areas,定位变得异常直观,只要把元素指定给对应的区域名字即可。

/* 对应上面 3.2 节的容器定义 */
.header-box {
grid-area: header;
}
.sidebar-box {
grid-area: sidebar;
}
.main-box {
grid-area: main;
}
.ads-box {
grid-area: ads;
}
.footer-box {
grid-area: footer;
}

4.3 自身的微调

  • justify-selfalign-self:允许个别元素脱离容器的统一指挥,在自己的格子里进行特定对齐。

五、Grid 杀手级实战场景

5.1 响应式卡片网格(Auto-fit 魔法)

这是最常见的需求:商品列表或图片画廊。要求卡片不能小于某个宽度(如 250px),当屏幕变宽时,自动在一行内塞入更多的卡片,填满空间。过去我们需要写一大堆 @media 查询来控制不同断点下的宽度百分比。在 Grid 中,只需一行代码

.card-gallery {
display: grid;
gap: 20px;
/* 核心魔法:
auto-fit 自动计算能放得下几列;
minmax 保证卡片最小 250px,最大平分剩余空间 (1fr)
*/
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

5.2 复杂杂志风格不规则排版

在很多设计感强的网站(如 Apple 官网介绍页)中,常看到大图占据几格、小图环绕的布局。

.magazine-layout {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 均分 4 列 */
grid-auto-rows: 200px; /* 如果未指定行数,自动生成的行高均为 200px */
gap: 15px;
}

.hero-image {
/* 头图,超级大,横跨 3 列,纵跨 2 行 */
grid-column: span 3;
grid-row: span 2;
}

.sub-image-1,
.sub-image-2 {
/* 旁边的小图,各自占默认的 1个格子 */
}

5.3 Holy Grail Layout (圣杯布局 Grid 终极版)

相比于 Flexbox 版本需要修改 HTML 顺序的麻烦,Grid 版本的圣杯布局保持了极度纯粹的语义化,并且在移动端重排时(只需重新画一下 areas)无比轻松:

<!-- HTML 结构完全没有任何嵌套 div,极致干净 -->
<body class="layout">
<header>头部</header>
<nav>导航</nav>
<main>核心内容</main>
<aside>侧边推荐</aside>
<footer>页脚</footer>
</body>
.layout {
display: grid;
min-height: 100vh;
/* 桌面端:三列布局 */
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'header header header'
'nav main aside'
'footer footer footer';
}

/* 结合媒体查询:当屏幕小于 768px 时,切换为移动端布局 */
@media (max-width: 768px) {
.layout {
/* 移动端:变为单列垂直流 */
grid-template-columns: 1fr;
grid-template-areas:
'header'
'nav'
'main'
'aside'
'footer';
}
}

总结

CSS Grid 是前端布局演进的顶峰之作。它不仅终结了多年的布局各种奇技淫巧,更重要的是,它将结构(HTML DOM)与呈现(CSS Layout)实现了几乎完全的解耦。掌握了 fr 单位的分配哲学、minmax 结合 auto-fit 的响应式魔法,以及直观的 grid-template-areas,你将能从容构建出任何天马行空的网页排版,而代码依然保持着惊人的整洁与优雅。