freeCodeCamp 课程挑战实战:用 CSS width 属性调整元素宽度及其自动评测实现解析
【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp
本篇围绕 freeCodeCamp 课程仓库中「Applied Visual Design(应用视觉设计)」模块下的一个 HTML/CSS 经典挑战——《Adjust the Width of an Element Using the width Property》展开。你将学到 CSSwidth属性的三类取值单位(绝对单位px、相对单位em、百分比)在真实页面布局中的用法,并深入该挑战的源码结构:从种子代码(seed)、参考答案到自动评分测试的完整实现链路。读完后,你既能掌握控制卡片类元素宽度的标准做法,也能理解 freeCodeCamp 如何用正则断言与getComputedStyle来验证学员代码。
挑战在课程中的定位
该挑战源文件位于 curriculum/challenges/english/blocks/applied-visual-design/587d7791367417b2b2512ab4.md,其 frontmatter 声明了挑战的元信息:
--- id: 587d7791367417b2b2512ab4 title: Adjust the Width of an Element Using the width Property challengeType: 0 forumTopicId: 301039 dashedName: adjust-the-width-of-an-element-using-the-width-property ---在课程结构文件 curriculum/structure/blocks/applied-visual-design.json 中,该挑战(challengeOrder中的第 2 项)紧随「Create Visual Balance Using the text-align Property」之后,排在「Adjust the Height of an Element Using the height Property」之前。这一编排体现了课程设计的渐进逻辑:先用text-align建立视觉平衡,再用width控制元素横向尺寸,随后用height控制纵向尺寸,构成对盒模型尺寸控制的完整铺垫。
从源码结构看,该 block 的blockLayout为legacy-challenge-list,helpCategory为HTML-CSS。而challengeType: 0的具体含义可以在共享配置包 packages/shared/src/config/challenge-types.ts 中确认:常量html的值就是0,并且:
viewTypes将类型为html的挑战映射为'classic'视图(challenge-types.ts 第 107 行),即经典的「编辑器 + 预览 + 测试输出」三栏界面;submitTypes将其映射为'tests'(challenge-types.ts 第 144 行),意味着提交后运行的是基于断言的自动化测试,而非项目链接提交。
同时,挑战的challengeType、description、instructions、forumTopicId等字段都需要通过 curriculum/schema/challenge-schema.js 中 Joi 模式的校验——例如challengeType限定为Joi.number().min(0).max(33),description对常规挑战类型是必填字符串。这保证了本挑战 frontmatter 的每个字段在构建期都会经过强校验。
核心知识点:width 属性的三类取值单位
挑战的--description--部分给出了本节的核心理论,原文档明确指出:
你可以使用 CSS 的
width属性来指定元素的宽度。取值可以是相对长度单位(如em)、绝对长度单位(如px),或者占父容器的百分比。
文档用了一个修改图片宽度的示例:
img { width: 220px; }这三类单位在实践中的差异值得展开:
| 取值形式 | 示例 | 特点与适用场景 |
|---|---|---|
| 绝对长度单位 | width: 220px | 精确到像素,渲染结果确定性强,适合需要固定尺寸的卡片、头像、缩略图等组件 |
| 相对长度单位 | width: 12em | 相对字体大小缩放,适合需要随字号联动的场景 |
| 百分比 | width: 80% | 相对父容器内容区宽度计算,是响应式布局的基础 |
本挑战刻意选择了245px这一绝对值,目的就是让评测可以精确比对,也让学员先建立「固定尺寸 = 确定像素值」的直观认知。
实战任务:为 .fullCard 卡片设定 245px 宽度
挑战的--instructions--指令是:
为整张卡片添加
width属性,并将其设置为绝对值 245px。使用fullCard类选择器选中该元素。
--seed--部分提供了初始页面,它是一个典型的「资料卡片」结构:外层.fullCard作为容器,内部依次是.cardContent(内边距 10px)、.cardText(含居中标题h4与两端对齐的段落p)和.cardLinks(两个外链,.links类带有margin-right: 20px):
<style> h4 { text-align: center; } p { text-align: justify; } .links { margin-right: 20px; text-align: left; } .fullCard { border: 1px solid #ccc; border-radius: 5px; margin: 10px 5px; padding: 4px; } .cardContent { padding: 10px; } </style> <div class="fullCard"> <div class="cardContent"> <div class="cardText"> <h4>Google</h4> <p>Google was founded by Larry Page and Sergey Brin while they were Ph.D. students at Stanford University.</p> </div> <div class="cardLinks"> <a href="#" target="_blank" class="links">Larry Page</a> <a href="#" target="_blank" class="links">Sergey Brin</a> </div> </div> </div>注意.fullCard规则体内刻意留了一个空行——这正是留给学员填写width: 245px;的位置。
参考答案(--solutions--)只改动了一行:
.fullCard { width: 245px; border: 1px solid #ccc; border-radius: 5px; margin: 10px 5px; padding: 4px; }这一行改动恰好落在盒模型的关键位置上。卡片已经同时声明了border: 1px solid #ccc、padding: 4px和margin: 10px 5px:在 CSS 默认box-sizing: content-box下,width: 245px只约束内容区宽度,元素实际占用的水平空间是245px + 2×4px(padding)+ 2×1px(border),再由margin与相邻元素保持间距。理解这一点,就理解了为什么本挑战先讲text-align(内容排版)、再讲width(尺寸)、最后讲height的顺序——每一步都在叠加盒模型的一个维度。
自动评测机制:正则断言 + 计算样式双重校验
该挑战--hints--部分内嵌的测试代码,展示了 freeCodeCamp 对「代码正确性 + 渲染正确性」的双重验证思路:
const fullCard = code.match(/\.fullCard\s*{[\s\S]+?[^}]}/g); const fullCardElement = document.querySelector('.fullCard'); const fullCardStyle = window.getComputedStyle(fullCardElement); assert.match(code,/\.fullCard\s*{[\s\S]+?[^}]}/g); assert.match(fullCard?.[0],/width\s*:\s*245px\s*(;|})/gi); assert.equal(fullCardStyle?.maxWidth, 'none');逐行解析这段评测逻辑:
code.match(/\.fullCard\s*{[\s\S]+?[^}]}/g):从学员提交的源码中正则提取.fullCard { ... }整段规则块,[\s\S]保证可以跨越换行匹配;assert.match(fullCard?.[0], /width\s*:\s*245px\s*(;|})/gi):在提取出的规则块内,验证存在width: 245px且其后紧跟分号或右花括号——\s*允许任意空白,(;|})防止width: 245px1之类的误判,i标志使PX/Px均通过;assert.equal(fullCardStyle?.maxWidth, 'none'):通过window.getComputedStyle读取实际渲染后的计算样式,断言max-width为默认值none。这条断言的意义在于:防止学员用max-width或其他属性「绕过」题目意图——题目要求的是直接指定width,而不是借助其他尺寸属性达到相似视觉效果。
这种「源码正则 + 运行时样式」的组合是 classic 类型挑战评测的典型模式:前者验证写法符合题目规范,后者验证浏览器中最终呈现的效果确实生效。
小结
通过 587d7791367417b2b2512ab4.md 这个挑战可以沉淀出三条可复用的知识:
width取值三要素:px(绝对)、em(相对)、%(相对父容器),本挑战选用245px固定卡片宽度;- 盒模型语境:
width与padding、border、margin共同决定元素占位,修改尺寸属性时必须结合box-sizing理解其真实效果; - 评测即规格:挑战内嵌的断言代码本身就是可执行的题目规格说明,正则约束书写格式、
getComputedStyle约束渲染结果,二者缺一不可。
若想继续深入,可参考同 block 中的后续挑战 Adjust the Height of an Element Using the height Property,以及课程结构定义 curriculum/structure/blocks/applied-visual-design.json 中完整的挑战顺序;若要了解所有挑战类型的枚举与视图/提交映射,可阅读 packages/shared/src/config/challenge-types.ts。
【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考