freeCodeCamp CSS Grid 课程实战:用 align-self 实现网格项的垂直对齐
本篇基于 freeCodeCamp 响应式网页设计课程(Responsive Web Design)中的 CSS Grid 练习块,围绕挑战 "Align an Item Vertically using align-self"(使用 align-self 垂直对齐网格项)展开。你将完整掌握 align-self 属性的取值与生效机制、它与 justify-self / align-items / justify-items 的关系,并能直接复现课程中的 3×3 网格练习、通过课程自带的断言正则验证自己的写法。
挑战在 CSS Grid 课程中的位置
这个挑战位于课程文件 curriculum/challenges/english/blocks/css-grid/5a90375238fddaf9a66b5d3b.md 中,属于 css-grid 块(块配置见 curriculum/structure/blocks/css-grid.json,helpCategory 为 HTML-CSS),并最终归属于响应式网页设计超级块(见 curriculum/structure/superblocks/responsive-web-design.json)。
从 块结构文件 中的 challengeOrder 可以看出,css-grid 块共编排了 21 个挑战,学习路径是循序渐进的:
- 先创建网格:
display: grid、grid-template-columns/grid-template-rows、fr 单位、grid-gap系列; - 再用
grid-column/grid-row控制跨度与间距; - 然后进入单元素对齐:
justify-self(水平)→align-self(垂直,即本挑战); - 最后进入容器级批量对齐:
justify-items(水平)→align-items(垂直)。
本挑战(dashedName: align-an-item-vertically-using-align-self)排在 justify-self 挑战(5a90374338fddaf9a66b5d3a.md)之后、justify-items 挑战(5a90376038fddaf9a66b5d3c.md)之前,属于课程中"单元素对齐"阶段的核心一环。
核心概念:单元格(cell)与 align-self
在 CSS Grid 中,每个网格项的内容所在的那个盒子被称为一个单元格(cell)。前一个挑战讲过:justify-self 负责把项的内容在单元格内水平对齐;本挑战要解决的是另一半——垂直方向的对齐。
挑战文档给出的描述是:
就像你可以水平对齐一个项一样,也可以垂直对齐一个项。做法是在该项上使用
align-self属性。该属性接受与上一个挑战中justify-self完全相同的取值。
结合前一个挑战 justify-self 文档 中对取值的完整说明,align-self 可接受的值为:
| 取值 | 在单元格内的垂直效果 |
|---|---|
stretch(默认) |
项拉伸填满单元格的整个高度 |
start |
内容靠单元格的顶部 |
center |
内容垂直居中 |
end |
内容靠单元格的底部 |
要点在于:align-self 写在网格项上,只对当前这一个项生效;这与后面 align-items(写在容器上、作用于所有项)形成对照。
练习场景:一个 3×3 的网格
挑战自带的种子代码(--seed-contents-- 部分)构建了一个 3 列 × 3 行的网格容器和 5 个彩色网格项:
<style>
.item1 {
background: LightSkyBlue;
}
.item2 {
background: LightSalmon;
}
.item3 {
background: PaleTurquoise;
/* Only change code below this line */
/* Only change code above this line */
}
.item4 {
background: LightPink;
}
.item5 {
background: PaleGreen;
}
.container {
font-size: 40px;
min-height: 300px;
width: 100%;
background: LightGray;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 10px;
}
</style>
<div class="container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
</div>
这段种子的关键配置值得逐项理解:
grid-template-columns: 1fr 1fr 1fr与grid-template-rows: 1fr 1fr 1fr:各建 3 条等宽列、3 条等高行,5 个项按源顺序自动落入前 5 个单元格(第 1 行 3 个、第 2 行 2 个);min-height: 300px:把容器高度撑开,让每个单元格内部出现明显富余空间——这正是垂直对齐可见化的前提。如果单元格与项等高,stretch默认值下看不出任何差异;grid-gap: 10px:行列间距统一为 10px(grid-gap是grid-column-gap和grid-row-gap的简写,对应块内更早的两个挑战);- 5 个项只设置了不同背景色(LightSkyBlue / LightSalmon / PaleTurquoise / LightPink / PaleGreen),没有显式高度,因此默认
stretch行为下会填满各自单元格。
任务指令(--instructions--)只有一句话:
将类名为
item3的项垂直对齐到end。
标准解法
在 .item3 规则内、两行注释之间加入一条声明即可:
.item3 {
align-self: end;
}
即修改后的 .item3 规则为:
.item3 {
background: PaleTurquoise;
align-self: end;
}
加上 align-self: end 后,第 3 个项(第一行第三列,PaleTurquoise 色)不再拉伸填满单元格高度,而是收缩并贴到单元格的底边,其上方留空——这就是"垂直对齐到 end"的可视化效果,其余四个项不受影响,仍然保持默认的 stretch 拉伸状态。
课程的自动化验证方式
该挑战属于 challengeType: 0(普通代码编辑挑战),课程的测试代码放在文档的 --hints-- 区块中,核心是一条正则断言:
assert.match(code, /.item3\s*?{[\s\S]*align-self\s*?:\s*?end\s*?;[\s\S]*}/gi);
拆开看这条正则的意图:
/.item3\s*?{/:定位.item3选择器的开括号(\s*?容忍选择器与花括号之间的任意空白);[\s\S]*align-self\s*?:\s*?end\s*?;:要求在规则体内出现align-self: end;,其中\s*?让冒号与等号两侧允许任意空白,因此写成align-self : end或align-self:end ;等宽松格式也能通过;- 末尾的
[\s\S]*}与g/i标志:规则体可以还有其他声明(如已有的background),且匹配不区分大小写。
从这条断言可以推断出课程对答案的判定标准是结构性的:只检查 .item3 规则中是否存在 align-self: end 声明,不检查具体行位置或缩进。这也意味着学习者可以在 /* Only change code ... */ 注释之间任意排版,只要声明存在即通过。
align-self 与同族属性的关系
把本挑战放进整个 css-grid 块的对齐四连击来看,四个属性的作用域恰好构成一个 2×2 的矩阵:
| 水平方向 | 垂直方向 | |
|---|---|---|
| 单个网格项(写在项上) | justify-self(见 justify-self 挑战) |
align-self(本挑战) |
| 所有网格项(写在容器上) | justify-items(见 justify-items 挑战) |
align-items(见 align-items 挑战) |
四个属性接受同一套取值(stretch / start / center / end),区别只在作用对象与方向:
- 本挑战要求"只动 item3 这一个",所以必须用项级的
align-self,而不是容器级的align-items; - 课程中 align-items 挑战 则是在
.container上写align-items: end,一次性把所有项都垂直贴底; - 当容器上的
align-items与项上的align-self同时存在时,从课程编排顺序(先项级、后容器级)和 CSS 级联的通用规则看,项级的align-self会覆盖容器级的对齐设定——这也是"self 系列优先于 items 系列"这一常见记忆口诀在课程语境下的体现。
小结与延伸
本挑战的最小改动只有一行——align-self: end;,但它承载了 CSS Grid 对齐体系的完整心智模型:
- 网格项默认在单元格内
stretch填满,只有当单元格富余空间可见(如min-height: 300px的 3×3 等分网格)时,对齐属性才产生可观察的视觉效果; align-self是"单点手术"工具,align-items是"全场广播"工具,两者取值相同、作用域不同;- 课程用一条正则断言(
align-self\s*?:\s*?end\s*?;)做宽容而明确的自动判分,写法宽松、判定标准单一。
想继续深入,可顺着 css-grid 块结构 中 challengeOrder 的后续条目,学习 grid-area 模板划分、repeat() / minmax() / auto-fill 等进阶主题;所有挑战的完整种子代码与解法都存放在 curriculum/challenges/english/blocks/css-grid/ 目录下,可按文件 id 直接查阅。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00