freeCodeCamp 应用视觉设计实战:用 CSS opacity 属性降低元素不透明度
本篇基于 freeCodeCamp 课程中 Responsive Web Design 认证下 Applied Visual Design 模块的挑战 “Decrease the Opacity of an Element”(源文件 587d781c367417b2b2512abf.md)展开,讲解 CSS opacity 属性的取值语义、整元素生效的渲染机制,以及如何在挑战给定的卡片页面上通过 .links 类选择器把锚点的不透明度设为 0.7,并完整给出种子代码、验收测试与官方解法,读者可以据此独立复现并理解该挑战的判定逻辑。
挑战在课程体系中的位置
该挑战文件的 Front Matter 声明了挑战元数据:id 为 587d781c367417b2b2512abf、challengeType 为 0、dashedName 为 decrease-the-opacity-of-an-element,并关联了一个教学视频和论坛话题 ID。其中 challengeType: 0 的含义可以在共享包中确认:在 challenge-types.ts 中 html 常量的值即为 0,表示这是一道经典 HTML/CSS 编辑器挑战,提交后以运行断言测试(submitTypes 中 html 对应 'tests')来判定通过。
课程结构上,该挑战由 applied-visual-design.json 中的 challengeOrder 数组编排,位于 “Add a box-shadow to a Card-like Element”(587d781b367417b2b2512abe)之后、“Use the text-transform Property to Make Text Uppercase”(587d781c367417b2b2512ac0)之前。整个 Applied Visual Design 块隶属于 responsive-web-design.json 定义的 Responsive Web Design 超级块,是该认证七大块之一,也是 “basic-css” 之后的进阶视觉设计部分。
由于挑战按顺序共享同一份卡片页面代码,可以观察到上一挑战 Add a box-shadow to a Card-like Element 的解法(为 #thumbnail 添加双阴影 box-shadow)已经完整带入本挑战的种子代码中——这正是本挑战页面里 #thumbnail 的 box-shadow 属性的来源。
opacity 属性的取值与生效机制
挑战正文对 opacity 的定义是:该属性用于调整元素的不透明度(opacity),反过来也就是透明度(transparency)。原文给出的取值语义:
A value of 1 is opaque, which isn't transparent at all. A value of 0.5 is half see-through. A value of 0 is completely transparent.
即取值范围为 0 到 1 的数值:1 完全不透明,0.5 半透明,0 完全透明。
正文还强调了一个关键的渲染机制:该数值作用于整个元素。无论元素是一张本身带有透明区域(如 PNG)的图片,还是一段拥有前景文字颜色和背景色的文本块,opacity 都会对元素的整个渲染结果(前景色、背景色、边框、阴影等)统一施加透明效果,而不是只作用于某一个颜色通道。这一点也是它与 rgba() 颜色写法中 alpha 通道的本质区别:本挑战页面的 h4 已经使用了 background-color: rgba(45, 45, 45, 0.1),那里的 alpha 值 0.1 只让这一个背景色变透明(该写法在上一个前置挑战 Adjust the background-color Property of Text 中刚被引入,原文说明 alpha 从 1(完全不透明)到 0(完全透明));而 opacity 是对元素整体的“整体调光”。
挑战要求与验收测试
本挑战的指令(instructions)只有一句话:
Set the
opacityof the anchor tags to 0.7 usinglinksclass to select them.
即:用 .links 类选择器选中两个锚点元素,将其 opacity 设为 0.7。
挑战附带的提示(hint)与自动化断言如下:
assert.match(
document.querySelector("style:not(.fcc-hide-header)")?.textContent,
/\.links\s*{([\s\S]*?;)*\s*opacity\s*:\s*0*\.70*\s*(;[\s\S]*?|\s*)}/
);
这段断言包含两层值得注意的实现细节:
- 选择器的排除逻辑。测试通过
style:not(.fcc-hide-header)定位“用户自己写的”<style>元素。为什么需要排除?从客户端源码结构看,平台在注入页面框架时会向页面插入一个带有fcc-hide-header类的<style>元素,frame.ts 中的注释明确说明该类的用途就是“确保 CSSHelper 类忽略这个 style 元素”。因此挑战的测试断言用同样的类名过滤,保证只检查学习者在编辑器中编写的样式,避免平台自身的样式干扰判定。 - 正则的书写容错。
\s*允许opacity、冒号、分号前后存在任意空白;0*\.70*的写法同时接受0.7、.7这类等价写法,因此只要.links规则块内出现语义正确的opacity: 0.7;声明即可通过,声明写在规则块内的其他声明之前或之后都不影响结果。
种子代码:继承自上一挑战的卡片页面
本挑战给出的完整起始代码(seed)如下,其中 .links 规则块目前只有 text-align 和 color 两条声明,留有一个空位等待补充:
<style>
h4 {
text-align: center;
background-color: rgba(45, 45, 45, 0.1);
padding: 10px;
font-size: 27px;
}
p {
text-align: justify;
}
.links {
text-align: left;
color: black;
}
#thumbnail {
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
}
.fullCard {
width: 245px;
border: 1px solid #ccc;
border-radius: 5px;
margin: 10px 5px;
padding: 4px;
}
.cardContent {
padding: 10px;
}
.cardText {
margin-bottom: 30px;
}
</style>
<div class="fullCard" id="thumbnail">
<div class="cardContent">
<div class="cardText">
<h4>Alphabet</h4>
<hr>
<p><em>Google was founded by Larry Page and Sergey Brin while they were <u>Ph.D. students</u> at <strong>Stanford University</strong>.</em></p>
</div>
<div class="cardLinks">
<a href="https://en.wikipedia.org/wiki/Larry_Page" target="_blank" class="links">Larry Page</a><br><br>
<a href="https://en.wikipedia.org/wiki/Sergey_Brin" target="_blank" class="links">Sergey Brin</a>
</div>
</div>
</div>
页面结构是一个经典的信息卡片(card):外层 div.fullCard#thumbnail 提供 245px 宽、1px 灰边、5px 圆角与双层投影;内部 .cardText 承载标题与正文,.cardLinks 容器内是两个带 links 类、指向维基词条的锚点,用 <br> 换行分隔。选择 .links 这个类而不是 a 标签选择器,是因为类选择器更精确地命中当前卡片内的两个链接,这正是本挑战想练习的选择器用法。
解法:在 .links 规则中追加一行声明
官方解法与种子代码的唯一差异,是在 .links 规则块内新增了 opacity: 0.7; 一行:
<style>
h4 {
text-align: center;
background-color: rgba(45, 45, 45, 0.1);
padding: 10px;
font-size: 27px;
}
p {
text-align: justify;
}
.links {
text-align: left;
color: black;
opacity: 0.7;
}
#thumbnail {
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
}
.fullCard {
width: 245px;
border: 1px solid #ccc;
border-radius: 5px;
margin: 10px 5px;
padding: 4px;
}
.cardContent {
padding: 10px;
}
.cardText {
margin-bottom: 30px;
}
</style>
<div class="fullCard" id="thumbnail">
<div class="cardContent">
<div class="cardText">
<h4>Alphabet</h4>
<hr>
<p><em>Google was founded by Larry Page and Sergey Brin while they were <u>Ph.D. students</u> at <strong>Stanford University</strong>.</em></p>
</div>
<div class="cardLinks">
<a href="https://en.wikipedia.org/wiki/Larry_Page" target="_blank" class="links">Larry Page</a><br><br>
<a href="https://en.wikipedia.org/wiki/Sergey_Brin" target="_blank" class="links">Sergey Brin</a>
</div>
</div>
</div>
效果上,两个黑色锚点会以 70% 的不透明度渲染,视觉上比正文文字略“淡”,形成一种常见的弱化链接样式。注意这里不需要也不应该改动 color: black——opacity 与颜色属性正交,它是在元素最终渲染之后再统一施加的透明系数;若写 opacity: 0,则包括文字、背景在内的整个锚点都不可见。
后续课程中 opacity 的进阶用法
在本模块的后半段,opacity 会再次出现在动画主题中。例如挑战 Create Visual Direction by Fading an Element from Left to Right 要求在 @keyframes 的 50% 关键帧里设置 opacity: 0.1,让一个小球在横移过程中逐渐淡出,制造从左到右的视觉引导。这说明本挑战教授的静态 opacity 声明,后续还会作为关键帧动画中的一个可动画属性被复用,是本模块知识链上承上(颜色/阴影)启下(transform/animation)的过渡点。
小结
opacity取值 0 到 1:1不透明、0.5半透明、0完全透明;它作用于元素的整个渲染结果(前景、背景、图片透明区域一并生效),区别于rgba()中只作用于单一颜色的 alpha 通道。- 本挑战要求用
.links类选择器为两个锚点设置opacity: 0.7;,种子代码与官方解法均完整给出,差异仅此一行。 - 验收断言通过
style:not(.fcc-hide-header)只读取学习者编写的样式(该过滤类名在 frame.ts 中有对应注入实现),并用允许等价写法的正则匹配声明。 - 挑战在课程中的位置由 applied-visual-design.json 的
challengeOrder编排,属于 Responsive Web Design 认证(responsive-web-design.json)的 Applied Visual Design 块,紧接 box-shadow 挑战之后,共享同一份卡片页面。
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 StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
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