首页
/ freeCodeCamp Basic CSS 挑战精讲:用 Hex 十六进制代码表示颜色(Use Hex Code for Specific Colors)

freeCodeCamp Basic CSS 挑战精讲:用 Hex 十六进制代码表示颜色(Use Hex Code for Specific Colors)

2026-09-06 17:47:40作者:仰钰奇

本篇指南基于 freeCodeCamp 课程仓库中的挑战文件 use-hex-code-for-specific-colors,完整讲解 CSS 中十六进制(hex)颜色代码的数学原理、表示规则与实操步骤,并结合仓库内的挑战校验逻辑、种子代码(seed)与标准答案(solutions),说明这道基础 CSS 题是如何被自动判分的。读完后你将掌握:hex 数与十进制数的对应关系、RRGGBB 六位颜色码的读写方法、在 <style> 中替换颜色写法,以及如何读懂课程仓库中挑战的测试断言与正则校验。

挑战在课程结构中的位置

该挑战属于 basic-css 区块,其区块元数据定义在 basic-css.json 中。从 challengeOrder 数组可以确认,"Use Hex Code for Specific Colors"(id 为 bad87fee1348bd9aedf08726)紧接在 "Override All Other Styles by using Important" 之后,排在颜色知识序列的起点,其后依次是:

  • "Use Hex Code to Mix Colors"(用 hex 混合颜色)
  • "Use Abbreviated Hex Code"(使用简写 hex)
  • "Use RGB values to Color Elements"(使用 RGB 值)

也就是说,本篇文档是整条"颜色表示法"学习链的第一环:先学会标准 6 位 hex 码,再学混色、简写和 RGB 等价写法。

挑战文件自身是带 YAML frontmatter 的 Markdown,frontmatter 中各字段含义如下:

字段 本文件取值 作用
id bad87fee1348bd9aedf08726 课程系统中该挑战的唯一标识,也是文件名
title Use Hex Code for Specific Colors 挑战标题
challengeType 0 挑战类型编号。在 challenge-types.ts 中,0 对应 HTML 类型,UI 分类映射为 'classic'(经典单文件 HTML/CSS 题)
videoUrl 一段外部视频教程地址 配套讲解视频(frontmatter 中为 scrimba 链接)
forumTopicId 18350 配套社区论坛帖子编号
dashedName use-hex-code-for-specific-colors URL 化的 slug,用于课程页面路由

核心知识一:十六进制数(Hex)是什么

文档首先解释了"颜色表示法"背后的数学基础。我们日常使用的**十进制(decimal)**是 base 10,每一位用 0~9 共 10 个符号表示。**十六进制(hexadecimal)**是 base 16,使用 16 个不同符号:

  • 09 表示数值 0~9(与十进制相同);
  • ABCDEF 分别表示数值 10~15。

因此单个十六进制位的取值范围是 0F,共 16 种可能值。这一进位规则正是后面"每两位 hex 恰好能表示一个 0~255 的通道分量"的关键(16 × 16 = 256)。

核心知识二:CSS 中用 6 位 hex 表示颜色

在 CSS 中,颜色用 6 个十六进制位表示,每两位分别对应红色(R)、绿色(G)、蓝色(B)三个分量,即 #RRGGBB 结构:

  • 红色分量 = 第 1~2 位;
  • 绿色分量 = 第 3~4 位;
  • 蓝色分量 = 第 5~6 位。

文档给出的示例是纯黑:#000000 三个通道分量均为 0,是色域的最低值:

body {
  color: #000000;
}

这套表示法建立在 RGB 颜色模型之上:每种颜色的"亮度"由红、绿、蓝三个分量的强度叠加决定。每个分量取 0~255 共 256 个级别,三个分量组合出 256³ ≈ 1677 万种颜色,这也是为什么 6 位 hex(每位 16 种取值,共 16⁶)与 RGB 三位十进制写法能覆盖完全相同的颜色范围——后文 RGB 挑战中也正是这样说明两者的等价性的。

实战:完成 "Use Hex Code for Specific Colors" 挑战

任务要求(instructions)

body 元素 background-color 中的颜色单词 black 替换为它的 hex 代码表示 #000000

初始代码(seed)

挑战加载到编辑器中的初始代码如下(来自文档 --seed-- 部分):

<style>
  body {
    background-color: black;
  }
</style>

标准答案(solutions)

只需把颜色单词换成 hex 写法:

<style>
  body {
    background-color: #000000;
  }
</style>

background-color: blackbackground-color: #000000 在浏览器中渲染结果完全一致,本挑战的目的正是让学习者建立"颜色名 ↔ hex 码"的映射习惯——这是后续混色(如橙色 #FFA500)与简写(如 #F00)的基础。

挑战如何判分:双重校验机制

文档 --hints-- 部分包含两条 JS 断言,揭示了该仓库对挑战答案的两层验证策略:渲染结果校验 + 源码模式校验

第一层:检查实际渲染出的计算样式

const body = document.querySelector('body');
const backgroundColor = window.getComputedStyle(body)['background-color'];
assert.strictEqual(backgroundColor, 'rgb(0, 0, 0)');

window.getComputedStyle 读取元素实际生效的样式。注意断言的期望值是 'rgb(0, 0, 0)' 而不是 '#000000'——因为浏览器会把 hex 颜色在计算样式中规范化(normalize)为 rgb() 形式。这解释了为什么"写 #000000"与"写 black"在这一层无法区分:两者渲染出来都是 rgb(0, 0, 0)

第二层:用正则约束源码写法

assert.match(code, /body\s*{(([\s\S]*;\s*?)|\s*?)background.*\s*:\s*?#000(000)?((\s*})|(;[\s\S]*?}))/gi);

这条正则直接匹配用户提交的 HTML 源码(变量 code),拆解其各部分:

  • body\s*{ ... }:锚定 body 选择器块,块内允许存在其他声明([\s\S]*; 部分可匹配前导的其他分号结尾声明);
  • background.*\s*:\s*?:匹配 background-color 等以 background 开头的属性赋值;
  • #000(000)?:核心约束——颜色值可以是 #000 也可以是 #000000,即 3 位简写与 6 位全写都通过;
  • ((\s*})|(;[\s\S]*?})):允许该声明后还有别的声明;
  • /gi 标志:不区分大小写(#000#000000 均可)、全局搜索。

两层断言合起来的含义是:渲染结果必须是黑色,且源码中必须显式使用 hex 字面量(#000#000000),不允许只写颜色名 black。这种"计算样式 + 源码正则"的组合是该仓库经典 HTML 挑战的典型判分模式(同区块的 RGB 挑战简写 hex 挑战 都采用相同结构)。

挑战文件在仓库中的结构约定

该文件整体遵循 freeCodeCamp 挑战 Markdown 的分节约定,用 # --section-- 标题划分区块:

分节 本文件内容 用途
# --description-- 十六进制原理、hex 颜色说明与示例代码 挑战页正文(学习材料)
# --instructions-- "把 black 换成 #000000" 任务说明
# --hints-- 两条 JS 断言 判分测试与提示
# --seed-- / ## --seed-contents-- 初始 HTML(background-color: black 编辑器初始代码
# --solutions-- 参考答案(background-color: #000000 标准解与自动测试基线

这些字段会被课程 schema 校验。在 challenge-schema.js 中,fileJoi 定义了每个代码文件对象必须包含的键,包括 seed第 29 行)与 contents 等;而 solutions 被校验为"由文件数组组成的非空数组"(第 365 行):

solutions: Joi.array().items(Joi.array().items(fileJoi).min(1)),

即每个挑战至少要有一个方案,每个方案至少包含一个可编辑文件——本文件的 --solutions-- 代码块正是填充这里的来源。

同系列挑战延伸:从 hex 到混色、简写与 RGB

读完本篇后,按 basic-css.json 中的顺序,接下来的三个挑战会依次加深同一主题:

  1. Use Hex Code to Mix Colors:讲解三个纯色通道如何按比例混合出 1600 多万年色。要点是 0 表示该通道完全缺失(无亮度),F 表示最大亮度。例如橙色是"满红 + 部分绿 + 无蓝",即 #FFA500(FF=255 满红,A5=165 中绿,00=无蓝)。该挑战要求把 red/green/dodgerblue/orange 四个颜色名替换为 #FF0000#00FF00#1E90FF#FFA500
  2. Use Abbreviated Hex Code:当 6 位 hex 的每一位两两相同时(#FF0000 → 每通道都是 FF),可压缩为 3 位:红色 #F00、绿色 #0F0、青色 #0FF、紫红色 #F0F。文档说明浏览器会将 #FF0000#F00 解释为完全相同的颜色,简写形式把可选颜色数降到约 4000 种(16³)。
  3. Use RGB values to Color Elements:介绍等价物 rgb(0, 0, 0)(黑)与 rgb(255, 255, 255)(白)。由于"hex 每两位 = 16 × 16 = 256 个值",RGB 的 0~255 与 hex 的两位完全等值,该挑战要求把 background-color: #F00 换成 rgb(0, 0, 0)

四种写法(颜色名、6 位 hex、3 位 hex、rgb())的对应关系可以整理为:

颜色 颜色名 6 位 hex 3 位 hex RGB
black #000000 #000 rgb(0, 0, 0)
red #FF0000 #F00 rgb(255, 0, 0)
绿 green #00FF00 #0F0 rgb(0, 255, 0)
cyan #00FFFF #0FF rgb(0, 255, 255)
orange #FFA500 —(不可简写) rgb(255, 165, 0)

注意橙色 #FFA500 每通道两位并不相同(FF/A5/00),因此没有等价的 3 位简写——这正是简写规则"每位必须两两相同"的直接推论。

本地复现与验证

想脱离课程平台练习这道题,可以保存一个静态 HTML 文件,例如 hex-color.html

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      background-color: #000000;
    }
  </style>
</head>
<body>
  <h1 style="color: white;">Hex color demo</h1>
</body>
</html>

用任意静态服务器或直接双击打开后,可在浏览器控制台执行挑战同款的第一层断言逻辑来验证:

const body = document.querySelector('body');
window.getComputedStyle(body)['background-color'];
// 期望输出: 'rgb(0, 0, 0)'

第二层正则断言则用于检查源码文本,把上面 assert.match 中的正则替换为你保存的文件内容即可自查。

小结

  • CSS 颜色可以用 6 位十六进制 #RRGGBB 表示,每个通道两位 hex 对应 0~255 的亮度(16² = 256 个级别),与 RGB 十进制表示一一对应;
  • 十六进制的 AF 代表 10~15,单个 hex 位有 16 种取值,6 位共 16⁶ ≈ 1677 万种颜色;
  • 本挑战要求把 bodybackground-color: black 改写为 background-color: #000000,答案与判分逻辑完整保存在 挑战源文件--solutions----hints-- 分节中;
  • 判分采用"计算样式断言(getComputedStyle 期望 rgb(0, 0, 0))+ 源码正则(#000(000)?)"双重校验,确保结果正确且写法符合要求;
  • 后续 混色简写 hexRGB 三个挑战在同一 区块顺序 中逐步展开完整的颜色表示法知识链。
登录后查看全文
热门项目推荐
相关项目推荐