首页
/ freeCodeCamp 应用视觉设计实战:用 CSS opacity 属性降低元素不透明度

freeCodeCamp 应用视觉设计实战:用 CSS opacity 属性降低元素不透明度

2026-09-06 12:33:23作者:滕妙奇

本篇基于 freeCodeCamp 课程中 Responsive Web Design 认证下 Applied Visual Design 模块的挑战 “Decrease the Opacity of an Element”(源文件 587d781c367417b2b2512abf.md)展开,讲解 CSS opacity 属性的取值语义、整元素生效的渲染机制,以及如何在挑战给定的卡片页面上通过 .links 类选择器把锚点的不透明度设为 0.7,并完整给出种子代码、验收测试与官方解法,读者可以据此独立复现并理解该挑战的判定逻辑。

挑战在课程体系中的位置

该挑战文件的 Front Matter 声明了挑战元数据:id587d781c367417b2b2512abfchallengeType0dashedNamedecrease-the-opacity-of-an-element,并关联了一个教学视频和论坛话题 ID。其中 challengeType: 0 的含义可以在共享包中确认:在 challenge-types.tshtml 常量的值即为 0,表示这是一道经典 HTML/CSS 编辑器挑战,提交后以运行断言测试(submitTypeshtml 对应 '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)已经完整带入本挑战的种子代码中——这正是本挑战页面里 #thumbnailbox-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 opacity of the anchor tags to 0.7 using links class 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*)}/
);

这段断言包含两层值得注意的实现细节:

  1. 选择器的排除逻辑。测试通过 style:not(.fcc-hide-header) 定位“用户自己写的” <style> 元素。为什么需要排除?从客户端源码结构看,平台在注入页面框架时会向页面插入一个带有 fcc-hide-header 类的 <style> 元素,frame.ts 中的注释明确说明该类的用途就是“确保 CSSHelper 类忽略这个 style 元素”。因此挑战的测试断言用同样的类名过滤,保证只检查学习者在编辑器中编写的样式,避免平台自身的样式干扰判定。
  2. 正则的书写容错\s* 允许 opacity、冒号、分号前后存在任意空白;0*\.70* 的写法同时接受 0.7.7 这类等价写法,因此只要 .links 规则块内出现语义正确的 opacity: 0.7; 声明即可通过,声明写在规则块内的其他声明之前或之后都不影响结果。

种子代码:继承自上一挑战的卡片页面

本挑战给出的完整起始代码(seed)如下,其中 .links 规则块目前只有 text-aligncolor 两条声明,留有一个空位等待补充:

<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 要求在 @keyframes50% 关键帧里设置 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.jsonchallengeOrder 编排,属于 Responsive Web Design 认证(responsive-web-design.json)的 Applied Visual Design 块,紧接 box-shadow 挑战之后,共享同一份卡片页面。
登录后查看全文
热门项目推荐
相关项目推荐