首页
/ freeCodeCamp 课程源码解析:用嵌套 CSS Grid 构建「网格中网格」布局

freeCodeCamp 课程源码解析:用嵌套 CSS Grid 构建「网格中网格」布局

2026-09-07 15:48:07作者:农烁颖Land

本篇以 freeCodeCamp 响应式设计课程中「Create Grids within Grids(在网格中创建网格)」这一练习(challenge)为蓝本,完整继承其种子代码、操作步骤与验证断言,并结合同一课程块(block)中的前置练习与课程结构文件,讲清 CSS Grid 嵌套布局的工作原理:把任意网格项(grid item)再声明为 grid 容器,即可得到层级化、可独立控制子项排布的多层网格。读完后,你将掌握嵌套网格的触发条件(只作用于直接子元素)、display: gridgrid-template-columns 的配合用法,以及如何用 frauto 等网格单位混合定义列宽。

核心概念:嵌套网格只影响直接子元素

freeCodeCamp 课程中该练习的原始描述(见 Create Grids within Grids)点出了嵌套网格的本质:

Turning an element into a grid only affects the behavior of its direct descendants. So by turning a direct descendant into a grid, you have a grid within a grid.

把任一元素设为网格容器后,CSS Grid 的排版规则只会作用于它的直接子元素,更深层的后代不受影响。反之,当你把网格容器的某个直接子元素(grid item)也设置 display: grid 时,该元素就成了一个独立的内层网格容器,它与自己的子元素构成一套完整的新网格——这就是「网格中的网格」。

这一特性对应到页面结构上非常直观:外层 .container 负责页面骨架(广告栏、页头、内容区、页脚),而内容区 .item3 内部的段落排版由它自己的网格规则决定,两层布局互不干扰、各自独立调整。

课程定位:css-grid 块中的最后一道练习

从课程结构文件 css-grid.json 可以看到,css-grid 块按 challengeOrder 顺序编排了 22 个练习,从 Create Your First CSS Grid 开始,依次覆盖列、行、间隙、对齐、grid-template-areas 区域模板、repeat/minmax/auto-fill 等函数,最终落在本练习「Create Grids within Grids」(id: 5a94fe8569fb03452672e464)。该块隶属于 responsive-web-design.json 超级块,即 freeCodeCamp 响应式设计认证课程的一部分。理解这一编排,有助于把握本练习为何是整块的收尾:前面各练习的知识点(网格单位、区域模板、grid-area 定位)在这里全部汇聚,用于构建一个真实感更强的多列页面骨架。

完整种子代码:一个带区域模板的外层网格

练习的种子代码(seed)定义了一个 3 行 2 列的页面骨架网格。完整代码如下,其中 .item3 内部预留了注释标记的改动区域:

<style>
  .container {
    font-size: 1.5em;
    min-height: 300px;
    width: 100%;
    background: LightGray;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr auto;
    grid-gap: 10px;
    grid-template-areas:
      'advert header'
      'advert content'
      'advert footer';
  }
  .item1 {
    background: LightSkyBlue;
    grid-area: header;
  }

  .item2 {
    background: LightSalmon;
    grid-area: advert;
  }

  .item3 {
    background: PaleTurquoise;
    grid-area: content;
    /* Only change code below this line */


    /* Only change code above this line */
  }

  .item4 {
    background: lightpink;
    grid-area: footer;
  }

  .itemOne {
    background: PaleGreen;
  }

  .itemTwo {
    background: BlanchedAlmond;
  }
</style>

<div class="container">
  <div class="item1">header</div>
  <div class="item2">advert</div>
  <div class="item3">
    <div class="itemOne">paragraph1</div>
    <div class="itemTwo">paragraph2</div>
  </div>
  <div class="item4">footer</div>
</div>

这段种子代码中蕴含了三个前置练习的知识点,建议对照原文件阅读:

  1. 区域模板 grid-template-areas:字符串模板 'advert header' / 'advert content' / 'advert footer' 把网格划成 headeradvertcontentfooter 四个命名区域,其中 advert 跨三行竖贯左侧。每个单词代表一个单元格,每对引号代表一行——这与前置练习 Divide the Grid Into an Area Template 的讲解一致。
  2. grid-area 定位网格项.item1.item4 各自通过 grid-area: header 等声明进入对应命名区域,见前置练习 Place Items in Grid Areas Using the grid-area Property
  3. 网格单位 frautogrid-template-columns: auto 1fr 表示第一列宽随内容自适应(auto),剩余空间全部分给第二列(1fr);grid-template-rows: auto 1fr auto 同理定义了三行。这些单位的语义(fr 为可用空间的一份、auto 由内容撑开、% 相对容器)在 Use CSS Grid units to Change the Size of Columns and Rows 中有完整说明。

值得注意的是,.itemOne.itemTwo 两个子元素目前只有背景色,没有任何网格规则——它们是内层网格的「占位项」,等待 .item3 成为网格容器后才被排版。

任务:把 item3 变成 auto 1fr 的两列网格

课程给出的原始指令是:

Turn the element with the item3 class into a grid with two columns with a width of auto and 1fr using display and grid-template-columns.

即使用 displaygrid-template-columns 两个属性,把 .item3 变成一个两列网格:第一列宽 auto(随子项内容宽度),第二列宽 1fr(占满内容区剩余空间)。标准答案只需在 .item3 的改动区域内补充两行声明:

.item3 {
  grid-template-columns: auto 1fr;
  display: grid;
}

两行声明的分工可以拆开看:

  • display: grid 是触发嵌套的关键。没有这一行,.item3 只是外层网格的一个普通项,内部的 .itemOne.itemTwo 会以普通的块级流纵向堆叠。
  • grid-template-columns: auto 1fr 定义内层网格的列模板,让两个段落子项各占一列:第一列被 paragraph1 的文字宽度撑开,第二列吃掉剩余宽度。由于声明只写在 .item3 上,外层 .container 的三行两列布局完全不受影响——这正是「网格只作用于直接子元素」这一规则的实际体现。

验证方式:正则断言检查声明是否写入正确的选择器

该练习属于 challengeType: 0(自由代码编辑型)的练习类型,freeCodeCamp 的课程数据格式用一组正则断言来验证学员代码是否满足要求。本练习的两条断言(引自原文档 --hints-- 部分)分别检查:

assert.match(
  code,
  /.item3\s*?{[\s\S]*grid-template-columns\s*?:\s*?auto\s*?1fr\s*?;[\s\S]*}/gi
);
assert.match(code, /.item3\s*?{[\s\S]*display\s*?:\s*?grid\s*?;[\s\S]*}/gi);

从正则结构可以看出课程对答案的判定标准:两条声明必须出现在 .item3 选择器块内部(正则从 .item3 { 开始,在其闭花括号范围内匹配),且 grid-template-columns 的值严格为 auto 1frdisplay 的值严格为 grid。这种「选择器 + 块内声明」的匹配方式,也间接提醒了嵌套网格的常见错误:把 display: grid 误写到外层 .container 或子项 .itemOne 上是通不过验证的,因为网格声明必须落在作为嵌套起点的那个直接子元素上。

延伸:从嵌套网格到响应式布局

嵌套网格解决的是「局部排版自治」问题,而 freeCodeCamp 的 css-grid 块中另一个练习 Use Media Queries to Create Responsive Layouts 则处理容器尺寸变化时的整体重排。二者结合正是本练习骨架的典型应用场景:外层 auto 1fr 让广告栏窄、内容区宽;内层 auto 1fr 让段落自适应文字;当视口变窄时,可以通过媒体查询改写内层的 grid-template-columns(例如改成单列 1fr),而不必触碰外层骨架。这种「每层网格各自定义列模板、各自响应断点」的分层思路,是 CSS Grid 构建复杂页面(如课程中出现的杂志版式、报纸版式布局练习,见 css-grid 超级块结构 中的 workshop-magazinelab-newspaper-layout)的基础模式。

小结

  • 嵌套条件:元素成为网格容器后,布局规则仅作用于其直接子元素;把某个 grid item 再声明为 display: grid,即得到网格中网格。
  • 本题解法:在 .item3 中加 display: grid;grid-template-columns: auto 1fr;,使其内部 paragraph1paragraph2 两子项形成两列内层网格。
  • 单位语义auto 由内容决定宽度,1fr 占满剩余可用空间,两者混合使用是「固定语义列 + 弹性内容列」的常见搭配。
  • 验证机制:课程用正则断言确认两条声明写在 .item3 选择器块内,体现了声明作用域对嵌套网格正确性的关键性。

完整原始题目、种子代码与参考答案见 curriculum/challenges/english/blocks/css-grid/5a94fe8569fb03452672e464.md,练习顺序见 curriculum/structure/blocks/css-grid.json

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388