freeCodeCamp 响应式网页设计实战:用 z-index 属性控制重叠元素的堆叠顺序
【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp
在 freeCodeCamp 的 Responsive Web Design 课程中,z-index是「Applied Visual Design」板块定位系列练习(relative → absolute → fixed → float → z-index → margin 居中)的收官知识点。本篇基于课程中的原始挑战文档,完整还原「Change the Position of Overlapping Elements with the z-index Property」这一练习的教学目标、起始代码与验收断言,并结合课程源码中的前后置挑战,讲清z-index的取值规则、生效条件及其在真实页面布局(弹窗、导航条、图层卡片)中的作用,读完即可掌握用position+z-index精确控制元素叠放顺序的完整方法。
z-index 解决什么问题:默认堆叠顺序
课程原文(z-index 挑战文档)对该问题的定义是:
当元素被定位成相互重叠时(即使用了
position: absolute | relative | fixed | sticky),默认情况下 HTML 标记中靠后出现的元素会显示在其他元素之上。但z-index属性可以指定元素在堆叠中的顺序。它的值必须是整数(whole number,不能是小数),z-index值更高的元素会叠放在值更低的元素之上。
也就是说,CSS 的默认行为是「后写者覆盖先写者」。这个默认规则有两个局限:
- 顺序被 HTML 结构绑死:想调整层级就必须调整 DOM 顺序,而 DOM 顺序还承担语义与无障碍(屏幕阅读器按标记顺序朗读)职责,不能随意调换;
- 层级无法表达「优先级」:导航条要永远压在正文之上、弹窗要压住导航条,用「谁写后面谁在上」来表达会非常脆弱。
z-index就是为打破这种绑定而设计的:它把「叠放顺序」从「DOM 顺序」中解耦出来,变成一个显式的、可调的数值维度。
挑战任务与完整代码
挑战的指令(instructions)是:
给类名为
first(红色矩形)的元素添加z-index属性并设为 2,让它覆盖另一个元素(蓝色矩形)。
课程的种子代码(seed,即练习开始时编辑器里的初始状态)完整如下:
<style> div { width: 60%; height: 200px; margin-top: 20px; } .first { background-color: red; position: absolute; } .second { background-color: blue; position: absolute; left: 40px; top: 50px; z-index: 1; } </style> <div class="first"></div> <div class="second"></div>观察这份种子代码可以发现三个教学意图:
- 两个
div都声明了position: absolute,因此脱离普通流并相互重叠——这是z-index能产生视觉差异的前提; .second(蓝矩形)已预设z-index: 1,相当于先给下层定好基准值;.first(红矩形)的样式块末尾刻意留了一行空位,提示学员「在这里补上缺失的规则」。
标准解法(solutions)只改了一处——给.first补上z-index: 2:
<style> div { width: 60%; height: 200px; margin-top: 20px; } .first { background-color: red; position: absolute; z-index: 2; } .second { background-color: blue; position: absolute; left: 40px; top: 50px; z-index: 1; } </style> <div class="first"></div> <div class="second"></div>效果对比:未修改前,.second在 HTML 中排在.first之后,按默认规则蓝矩形压在红矩形上;修改后.first的z-index: 2大于.second的z-index: 1,红矩形反压回来,覆盖蓝矩形。
验收断言如何验证
课程对这类挑战的判定代码写在文档的--hints--段,核心是用浏览器计算样式做精确断言:
const firstElement = document.querySelector('.first'); const firstStyle = window.getComputedStyle(firstElement); assert.equal(firstStyle?.zIndex, '2');从断言细节可以看出两个实现事实:
- 检查的是
getComputedStyle的计算值而非源码文本,说明判定与书写格式无关,只关心最终生效的样式; - 断言右侧是字符串
'2'而非数字2。这符合 CSSOM 的行为——getComputedStyle返回的样式值统一是字符串,z-index作为整数在计算样式中呈现为无单位数字字符串'2'。
z-index 的两个硬性规则:从源码与前后挑战印证
规则一:只对定位元素生效
原文档明确列出z-index的适用前提:元素必须是position: absolute | relative | fixed | sticky之一。这一点在课程定位系列的前置挑战里都有对应铺垫:
- Change an Element's Relative Position 讲解
position: relative配合top/bottom/left/right偏移,并强调「relative 不会把元素移出普通流」; - Lock an Element to its Parent with Absolute Positioning 讲解
position: absolute会「移除元素脱离普通流(removes the element from the normal flow)」,并说明它会锚定到最近的定位祖先(通常是给父级加上position: relative); - 本 z-index 挑战的种子代码正是把
absolute用到了两个矩形上。
因此可以这样理解整条知识链:position决定元素是否进入堆叠参与竞争,z-index决定竞争名次。对position: static(默认值)的普通流元素,写z-index是无效的——这是新手最常踩的坑,也是课程把本练习安排在四种position取值讲完之后(float 之后、margin 居中之前)的原因。从 Applied Visual Design 板块结构 可以看到本挑战在challengeOrder中的位置:它紧接Push Elements Left or Right with the float Property之后、Center an Element Horizontally Using the margin Property之前,属于定位主题(relative → absolute → fixed → float → z-index)的收尾。
规则二:值必须是整数
原文强调 It must be an integer (i.e. a whole number and not a decimal)。取值要点:
| 特性 | 说明 |
|---|---|
| 允许的值 | 任意整数:正数、负数、0 |
| 不允许的值 | 小数(如1.5)、单位(如2px)、百分比 |
| 默认值 | 未定位元素为auto;定位元素按 DOM 顺序参与堆叠 |
| 比较方式 | 数值大者在上面,与选择器优先级(specificity)无关 |
| 负值用途 | 把定位元素压到同层其他元素之后,常用来做底层装饰 |
需要补充一个课程文档没有直接展开、但从源码结构可以合理推断的工程要点:z-index只在同一个**堆叠上下文(stacking context)**内比较。当某个定位元素自身设置了非auto的z-index(或 opacity、transform 等会创建新上下文的属性)时,它的后代元素的z-index只在「自家」上下文内有效,对外只表现为该上下文整体的名次。这解释了为什么有时给子元素调z-index却「顶不过」兄弟元素——实际要调的是父级上下文。
实战延伸:z-index 的典型应用场景
结合课程中其他挑战的形态,z-index在日常开发中最常见的三类用法是:
- 固定导航条/工具条:给
position: fixed的 header 一个较高值(如z-index: 1000),保证滚动内容永远在其下方; - 弹窗与遮罩:遮罩层用
z-index: 100,弹窗本体用z-index: 101,弹窗内的关闭按钮再高一层; - 卡片/标签角标:让角标、徽章(badge)压在卡片内容之上,或让某张卡片作为「置顶」样式突出显示。
工程上常见的做法是建立层级阶梯(z-index scale):例如把布局类元素限定在 1–99、UI 层在 100–999、模态层在 1000+,避免随手写z-index: 9999造成全局混乱。这不属于本课程的断言范围,但属于该知识点落地时的通行约定。
在课程中的位置与学习路径
本挑战隶属 Responsive Web Design 证书下的 Applied Visual Design 板块。从 responsive-web-design.json 可见,该 superblock 的板块顺序为:basic-html-and-html5→basic-css→applied-visual-design→applied-accessibility→responsive-web-design-principles→css-flexbox→css-grid。也就是说,z-index所学的position/float定位属于传统布局手段,课程在后续 Flexbox 与 Grid 板块中会给出更现代的布局方案;理解z-index的价值在于它是贯穿所有布局模式(包括 Flex 与 Grid)的通用层级工具。
本章后续可顺学的相关练习:
- Center an Element Horizontally Using the margin Property:用
margin: auto水平居中,是定位主题的最后一块拼图; - Push Elements Left or Right with the float Property:本挑战的直接前置,理解
float如何把元素移出普通流,是理解为何浮动元素也需要z-index参与叠放的基础。
小结
z-index只在元素为absolute / relative / fixed / sticky定位时生效,用于显式指定叠放名次;- 它必须取整数,值越大越靠上;未设置时按 DOM 顺序「后写者在上」;
- 课程练习的验收方式是
getComputedStyle(el).zIndex与字符串'2'相等,关注的是计算后的最终值; - 实际工程中建议按「布局 < 工具栏 < 弹窗」的思路规划 z-index 阶梯,并注意堆叠上下文对子元素层级的限制。
【免费下载链接】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),仅供参考