freeCodeCamp CSS Grid 课程实战:用 grid-gap 简写属性为网格行列快速设置间距
本文以 freeCodeCamp 课程(curriculum)中 CSS Grid 模块的练习题 "Add Gaps Faster with grid-gap" 为核心,完整讲解 grid-gap 简写属性的取值规则——单值与双值分别控制什么、如何在网格容器上设置"行间距 10px、列间距 20px"的标准答案写法,并结合该挑战文件在课程中的前后文、自动测试断言的实现方式,帮助你在掌握这个属性的同时理解 freeCodeCamp 练习题的定义结构与验证机制。
1. 挑战定位:CSS Grid 课程中的第 7 关
在 freeCodeCamp 的课程源码中,每道练习题都是一个带 frontmatter 的 Markdown 文件。本文对应的挑战文件为 add-gaps-faster-with-grid-gap,其 frontmatter 声明了关键元信息:
id: 5a9036ee38fddaf9a66b5d37
title: Add Gaps Faster with grid-gap
challengeType: 0
dashedName: add-gaps-faster-with-grid-gap
challengeType: 0 表示这是一道普通的编码挑战(code challenge),dashedName 则用于生成学习页面的 URL 片段。
挑战在模块中的位置由 css-grid 模块结构文件 中的 challengeOrder 数组决定。从源码结构看,该数组按顺序排列了 22 道挑战,本文挑战(id 5a9036ee38fddaf9a66b5d37)排在第 7 位,其紧邻的前两道题分别是:
- 第 5 题 "Create a Column Gap Using grid-column-gap",对应 grid-column-gap 挑战文件,讲解如何用
grid-column-gap: 20px;在列之间加间距; - 第 6 题 "Create a Row Gap using grid-row-gap",对应 grid-row-gap 挑战文件,讲解如何用
grid-row-gap: 5px;在行之间加间距。
grid-gap 正是这两个属性的合并简写——这正是本关标题 "Add Gaps Faster" 的含义:一行属性替代两行属性。再往前一题 "Use CSS Grid units to Change the Size of Columns and Rows"(对应文件)则铺垫了 fr、auto、% 等轨道尺寸单位,是本关 seed 代码中 1fr 1fr 1fr 的来源。
从课程组织上看,css-grid 这个 block 已被纳入更新的 "Learn CSS Grid by building a magazine" 项目,见 responsive-web-design-22 超级块结构 与 css-grid 超级块结构(后者还包含 lecture-working-with-css-grid、quiz-css-grid、review-css-grid 等配套教学块)。也就是说,本关不是孤立知识点,而是整个 CSS Grid 教学体系里"间距"环节的最终收束。
2. 核心知识点:grid-gap 的单值与双值语义
挑战文档的 --description-- 一节给出了本关的核心概念(原文完整保留):
grid-gapis a shorthand property forgrid-row-gapandgrid-column-gapfrom the previous two challenges that's more convenient to use. Ifgrid-gaphas one value, it will create a gap between all rows and columns. However, if there are two values, it will use the first one to set the gap between the rows and the second value for the columns.
将其展开为明确的规则表:
| 写法 | 等价展开 | 效果 |
|---|---|---|
grid-gap: 10px; |
grid-row-gap: 10px; grid-column-gap: 10px; |
行、列使用相同间距 |
grid-gap: 10px 20px; |
grid-row-gap: 10px; grid-column-gap: 20px; |
行间距取第一个值,列间距取第二个值 |
需要注意一个与 margin 简写不同的细节:grid-gap 的双值语法里,第一个值永远是行间距(row gap),第二个值永远是列间距(column gap),顺序固定,不能调换。本关的任务要求(--instructions--)恰好就是双值场景:
Use
grid-gapto introduce a10pxgap between the rows and20pxgap between the columns.
3. 实操:Seed 代码与标准答案
本关的 seed 代码(--seed-contents--)构建了一个 3 列 × 3 行的网格容器,5 个彩色子项自动按行优先排布:
<style>
.d1 {
background: LightSkyBlue;
}
.d2 {
background: LightSalmon;
}
.d3 {
background: PaleTurquoise;
}
.d4 {
background: LightPink;
}
.d5 {
background: PaleGreen;
}
.container {
font-size: 40px;
min-height: 300px;
width: 100%;
background: LightGray;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
/* Only change code below this line */
/* Only change code above this line */
}
</style>
<div class="container">
<div class="d1">1</div>
<div class="d2">2</div>
<div class="d3">3</div>
<div class="d4">4</div>
<div class="d5">5</div>
</div>
.container 上已有的属性各自承担一个职责:
display: grid;将容器变为网格格式上下文,是后续所有grid-*属性生效的前提;grid-template-columns: 1fr 1fr 1fr;创建三条等宽列轨道(1fr表示均分剩余空间);grid-template-rows: 1fr 1fr 1fr;创建三条等高行轨道;min-height: 300px;保证容器在子项高度不足时仍有可视区域。
两行 /* Only change code ... */ 注释框出了作答区间,学员只需在其中补一行:
.container {
grid-gap: 10px 20px;
}
即 --solutions-- 一节给出的参考答案。渲染效果上:5 个子项占据第 1、2 行的前 5 个网格单元,水平方向相邻子项之间出现 20px 空隙,垂直方向出现 10px 空隙,未被占用的网格区域则露出容器的 LightGray 底色。
为什么断言要求 10px 在前、20px 在后
挑战文件 --hints-- 一节内置了用于自动判分的正则断言:
assert.match(
code,
/.container\s*?{[\s\S]*grid-gap\s*?:\s*?10px\s+?20px\s*?;[\s\S]*}/gi
);
这条正则的关键片段 grid-gap\s*?:\s*?10px\s+?20px\s*?; 精确要求:grid-gap 之后必须先是 10px,中间以空白分隔,再跟 20px。这与 CSS 规范中"双值时第一值为行间距、第二值为列间距"的语义一一对应——写反成 grid-gap: 20px 10px; 虽然语法合法,但语义变成了"行间距 20px、列间距 10px",与题目要求不符,断言也会失败。这是学习 CSS 简写属性时值得养成的习惯:简写的值顺序由规范固定,写之前先确认每个位置代表什么。
4. 补充说明:grid-gap 与现代 gap 的关系
挑战文档写作于 CSS Grid 属性早期命名阶段,使用的是 grid-gap / grid-row-gap / grid-column-gap 这套旧名。从仓库客户端源码的结构可以印证后续演进:freeCodeCamp 站点自身的前端样式已普遍采用更短的 gap 简写,例如 landing.css 中存在 gap: 30px; /* Adjust the space between the grid items */ 这样为网格项调整间距的写法,universal-nav.css 等文件也有 gap: 10px; 的用法。
可以这样理解二者关系:gap 是 grid-gap 的规范化后继,取值语义完全一致(单值 = 行列同值,双值 = 行值在前、列值在后),并且 gap 同时适用于 flex 布局;grid-row-gap / grid-column-gap / grid-gap 则被标记为 legacy 写法。因此学习本关时应把重点放在"单值/双值的顺序语义"上——这套规则在 gap: 10px 20px; 中同样成立,可以直接迁移到现代项目。
5. 举一反三:三种间距写法的等价对照
结合本关与前两关,可以把三种等价实现放在一起对比,帮助巩固取值顺序:
/* 写法一:分设两个属性(前两关的知识点) */
.container {
grid-row-gap: 10px;
grid-column-gap: 20px;
}
/* 写法二:grid-gap 双值(本关答案) */
.container {
grid-gap: 10px 20px;
}
/* 写法三:现代 gap 简写(与 grid-gap 语义相同,且可用于 flex 布局) */
.container {
gap: 10px 20px;
}
三者的视觉效果完全一致。若只需统一间距,则退化为单值形式 grid-gap: 10px; 或 gap: 10px;。
6. 小结
grid-gap是grid-row-gap与grid-column-gap的简写:单值同时作用于行列,双值时第一个值为行间距、第二个值为列间距;- 本关标准答案是
.container { grid-gap: 10px 20px; },自动判分通过 --hints-- 中的正则/.container\s*?{[\s\S]*grid-gap\s*?:\s*?10px\s+?20px\s*?;[\s\S]*}/gi验证; - 该挑战是 css-grid 模块 22 道挑战中的第 7 道,承上(
grid-column-gap、grid-row-gap、fr单位)启下(grid-column、grid-row控制跨列跨行); grid-gap的取值顺序语义已完整继承到现代gap属性中,freeCodeCamp 站点自身样式中也已大量使用gap简写,掌握后可直接用于实际开发。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0630
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00