freeCodeCamp 课程设计详解:用 CSS font-size 属性设置段落文字大小(Set the font-size of Paragraph Text)
本文基于 freeCodeCamp 课程库中 Applied Visual Design(应用视觉设计)模块的一道实战挑战展开,讲解 CSS font-size 属性如何从标题元素扩展到任意包含文本的元素(以段落 <p> 为例)、该挑战在课程编排中的位置,以及 freeCodeCamp 如何用 getComputedStyle 断言在浏览器中自动验证学员答案。读完后你将掌握段落字号的设定方法、font-size 的取值惯例,以及该课程库挑战文件的完整结构与自动测试机制。
挑战在课程中的位置与元数据
这道挑战的挑战文件位于 applied-visual-design 挑战目录,其 YAML frontmatter 定义了挑战的身份信息:
id: 587d781c367417b2b2512ac4
title: Set the font-size of Paragraph Text
challengeType: 0
videoUrl: 'https://scrimba.com/c/cVJ36Cr'
forumTopicId: 301068
dashedName: set-the-font-size-of-paragraph-text
各字段的含义从课程库的结构约定看:
| 字段 | 取值 | 作用 |
|---|---|---|
id | 587d781c367417b2b2512ac4 | 挑战的唯一标识,同时是挑战文件名的来源 |
title | Set the font-size of Paragraph Text | 挑战标题,在课程目录中展示 |
challengeType: 0 | 0 | 表示这是标准的 HTML/CSS 编辑器类挑战(在代码编辑区作答) |
videoUrl | Scrimba 课程链接 | 配套视频讲解地址 |
forumTopicId | 301068 | 官方论坛对应讨论帖的 ID,便于学员求助 |
dashedName | set-the-font-size-of-paragraph-text | 用于生成 URL 友好路径的连字符名称 |
挑战的编排顺序由块级结构文件 applied-visual-design.json 中的 challengeOrder 数组决定。该块声明了 "dashedName": "applied-visual-design"、"helpCategory": "HTML-CSS",并标注 "blockLayout": "legacy-challenge-list"。从 challengeOrder 的排列看,本挑战夹在两道同主题挑战之间:
- 前一道:Set the font-weight for Multiple Heading Elements(为多个标题设置 font-weight);
- 后一道:Set the line-height of Paragraphs(设置段落的 line-height)。
也就是说,课程在这里用连续几道挑战构建了"文本样式"知识链:先学标题字号、字重,再学段落字号、行高,逐层推进。
核心概念:font-size 不仅适用于标题
挑战描述(# --description-- 段)给出的核心知识点只有一句话,但它是理解本题的关键:
The
font-sizeproperty in CSS is not limited to headings, it can be applied to any element containing text.(CSS 中的
font-size属性并不局限于标题,它可以应用到任何包含文本的元素上。)
这一点是承接上一道挑战 Set the font-size for Multiple Heading Elements 的。在前一道挑战中,学员已经为 h1 到 h6 设定了递减的字号阶梯,形成页面标题层级:
| 元素 | font-size |
|---|---|
h1 | 68px |
h2 | 52px |
h3 | 40px |
h4 | 32px |
h5 | 21px |
h6 | 14px |
而 font-size 同样可以写入 <p> 这样的正文段落选择器中。本挑战正是把这条规则从标题迁移到段落:初始代码故意把段落字号调得很小(10px),要求学员把它调回 16px 使文本更易读。16px 也是浏览器对正文元素的默认字号,这解释了任务说明(# --instructions-- 段)的原话:
Change the value of the
font-sizeproperty for the paragraph to 16px to make it more visible.(把段落的
font-size属性值改为 16px,让它更清晰可见。)
实战操作:初始代码与目标答案
挑战的初始代码(--seed-contents-- 段)是一段可直接在浏览器中打开的完整 HTML 页面:
<style>
p {
font-size: 10px;
}
</style>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
学员需要做的唯一修改,是把选择器 p 下的 font-size 从 10px 改为 16px。挑战文件给出的参考解法(# --solutions-- 段)为:
<style>
p {
font-size: 16px;
}
</style>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
几点值得注意的细节:
- 样式写在
<style>标签内部,属于内联样式表,作用于页面内所有<p>元素,因此这里用的是元素选择器p而不是类选择器; font-size的取值使用px(像素)单位,这是该模块所有挑战统一采用的单位(前文标题阶梯中的 68px~14px 均为像素值);- 段落文本是一段经典的 Lorem ipsum 占位文本,目的是让多行文字在 10px 与 16px 两种字号下的可读性差异在预览区一目了然。
答案验证机制:基于 getComputedStyle 的浏览器断言
freeCodeCamp 的编辑器类挑战(challengeType: 0)在学员点击"运行测试"时,会注入一段 JavaScript 断言脚本检查 DOM 上的实际计算样式。本挑战的测试代码(# --hints-- 段)为:
const pElement = document.querySelector('p')
const pStyle = window.getComputedStyle(pElement);
assert.equal(pStyle?.fontSize, '16px');
这段测试逻辑拆解如下:
document.querySelector('p')取出页面中第一个(也是唯一一个)段落元素;window.getComputedStyle(pElement)获取该元素计算后的样式对象,而不是读取<style>标签里的源码文本——这意味着只有真正生效的样式才能通过断言;- 注意比较的是字符串
'16px':getComputedStyle返回的fontSize是规范化后的字符串形式(小写、带单位),如果学员写成16 px、1.6rem或16PX等不产生16px计算值的写法,断言都会失败; - 链式可选访问
pStyle?.fontSize是一种防御式写法,当p元素不存在时pStyle为undefined,避免抛出运行时错误。
同一模块的姊妹挑战(如前文提到的 h1 字号挑战)采用了相同的验证模式:部分用 getComputedStyle(如本挑战),部分用封装好的 __helpers.CSSHelp 工具类读取样式并比较 getPropertyValue('font-size') 的返回值。两者殊途同归,都是"检查计算后样式是否等于期望的像素字符串"。
从课程设计的角度,这种验证方式迫使学员理解:CSS 的最终效果体现在计算样式上,而不是写在哪个选择器里——这对建立正确的 CSS 心智模型是有价值的。
知识链的延续:从字号到行高
本挑战的解法会直接成为下一道挑战的起点。查看后继挑战 Set the line-height of Paragraphs 的初始代码可以看到,它的 seed 正是承接本题答案的:
<style>
p {
font-size: 16px;
}
</style>
(空行处留给学员补写 line-height: 25px。)这种"上一题解法即下一题起点"的链式编排,是 freeCodeCamp 课程库中同一主题挑战的常见组织方式:每道挑战只引入一个新知识点,而页面上已有的样式作为上下文保留下来。
往前看,Set the font-weight for Multiple Heading Elements 也在做同样的事——为 h1~h6 分别设置 800、600、500、400、300、200 的字重,并明确写道 "You set the font-size of each heading tag in the last challenge, here you'll adjust the font-weight"(上一题你设置了每个标题标签的 font-size,这里你调整 font-weight),形成了字号 → 字重 → 段落字号 → 行高的完整学习路径。
挑战文件的组织结构
freeCodeCamp 课程库中的每道挑战都是一个 Markdown 文件,存放在 curriculum/challenges/english/blocks/<块名>/<id>.md 下(本例中块名为 applied-visual-design,文件名即挑战 id)。文件内部用固定的标题锚点划分段落,本挑战完整覆盖了以下部分:
| 段落标记 | 内容 |
|---|---|
frontmatter(--- 之间) | 元数据:id、title、challengeType、videoUrl、forumTopicId、dashedName |
# --description-- | 知识点讲解 |
# --instructions-- | 具体任务指令 |
# --hints-- | 提示说明,其中内嵌 JavaScript 测试断言代码块 |
# --seed-- / ## --seed-contents-- | 学员打开编辑器时看到的初始 HTML 代码 |
# --solutions-- | 参考解法 |
这些段落约定并非随意:课程仓库在 curriculum/schema 目录下维护了挑战文件的校验 schema(如 challenge-schema.js),curriculum/src/get-challenges.ts 等脚本负责把这些 Markdown 文件解析并聚合为课程内容。因此,--seed-contents-- 与 --solutions-- 中内嵌的 HTML 代码块是学员实际运行和被判题依据的真实载体,而非仅仅是文档示例。
小结
font-size适用于任何包含文本的元素,p { font-size: 16px; }即可提升段落可读性;本挑战从 10px 改到 16px,16px 同时是浏览器正文默认字号。- freeCodeCamp 用
window.getComputedStyle读取计算样式并断言字符串'16px',验证的是样式实际生效后的结果。 - 挑战文件以固定 Markdown 锚点组织(description/instructions/hints/seed/solutions),配合
curriculum/structure/blocks/*.json中的challengeOrder形成链式学习路径:标题字号 → 字重 → 段落字号 → 行高。
如需继续学习,可按 challengeOrder 顺序阅读同一目录下的前后挑战,例如 h1~h6 字号挑战 与 line-height 挑战,它们与本挑战共享同一套测试与编排机制。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



