【CSS in Depth 2 精译_041】6.4 CSS 中的堆叠上下文与 z-index(上)

当前内容所在位置(可进入专栏查看其他译好的章节内容)

  • 第一章 层叠、优先级与继承(已完结)
  • 第二章 相对单位(已完结)
  • 第三章 文档流与盒模型(已完结)
  • 第四章 Flexbox 布局(已完结)
  • 第五章 网格布局(已完结)
  • 【第六章 定位与堆叠上下文】 ✔️
    • 6.1 固定定位
      • 6.1.1 创建一个固定定位的模态对话框
      • 6.1.2 在模态对话框打开时防止屏幕滚动
      • 6.1.3 控制定位元素的大小
    • 6.2 绝对定位
      • 6.2.1 关闭按钮的绝对定位
      • 6.2.2 伪元素的定位问题
    • 6.3 相对定位
      • 6.3.1 创建下拉菜单(上)
      • 6.3.2 创建 CSS 三角形(下)
    • 6.4 堆叠上下文与 z-index ✔️
      • 6.4.1 理解渲染过程与堆叠顺序(上) ✔️
      • 6.4.2 用 z-index 控制堆叠顺序(上) ✔️
      • 6.4.3 深入理解堆叠上下文(下)(精译中 ⏳)

文章目录

    • [6.4 堆叠上下文与 z-index(Stacking contexts and z-index)](#6.4 堆叠上下文与 z-index(Stacking contexts and z-index))
      • [6.4.1 理解渲染过程与堆叠顺序 Understanding the rendering process and stacking order](#6.4.1 理解渲染过程与堆叠顺序 Understanding the rendering process and stacking order)
      • [6.4.2 用 z-index 控制堆叠顺序 Manipulating stacking order with z-index](#6.4.2 用 z-index 控制堆叠顺序 Manipulating stacking order with z-index)

《CSS in Depth》新版封面

译者按

前面利用 CSS 的定位技术相继实现了模态对话框和下拉菜单的效果,这一节将重点处理二者在页面渲染时出现的意外堆叠问题。本节内容非常重要,由于篇幅较长,特地分为上篇和下篇进行介绍。本篇为上篇,先讲讲堆叠问题的具体处理。下一篇再深入原理,彻底弄清堆叠上下文的核心概念及行为模式。其实阻碍前端开发人员进阶中高级水平的,往往就是这些平时就掌握得模棱两可的核心概念,即便工作中遇到过,事后也鲜有及时复盘与梳理。让我们跟随作者的脚步,一起持续深耕,潜心积累!

6.4 堆叠上下文与 z-index(Stacking contexts and z-index)

定位技术(Positioning)固然实用,但更重要的是弄明白它会带来什么样的意外情况。一个元素自从脱离文档流后,之前由文档流负责的工作从此也将由您来全面接管。

比如,要时刻确保该元素不会意外跑到浏览器视口(viewport)的外面,让用户找不着它;其次,必须保证该元素不会意外挡住页面上的重要内容。

最后还要考虑元素堆叠(stacking)方面的问题。在同一页面定位多个元素时,很可能会遇到两个不同的定位元素发生重叠的情况,并且偶尔还会发现它们并没有乖乖按照我们预想的方式进行重叠。其实本章的示例已经有意设置了这样的问题场景,以便进一步演示该如何处理。

根据之前示例页面的设计需求,点击页面顶部的注册按钮(即 "Sign up" 字样的按钮)就能打开一个模态对话框。要是把下拉菜单相关的 HTML 标记放到模态框的源码后面,最终效果就会如下图 6.10 所示,下拉菜单意外挡在了模态对话框的前面:

图 6.10 模态框错误地出现在下拉菜单的后面

解决这个问题有很多种方案。在此之前,有必要先了解一下浏览器确定元素堆叠顺序的基本原理。为此,需要进一步考察一个页面在浏览器中的渲染过程。

6.4.1 理解渲染过程与堆叠顺序 Understanding the rendering process and stacking order

在浏览器将 HTML 解析为 DOM 时,它还会同步创建一个新的树形结构,称为 渲染树(render tree 。该渲染树不仅体现了每个元素的视觉样式和位置,同时也决定着浏览器 绘制(paint 这些元素的顺序。该顺序 极其重要:一旦发生重叠,后绘制的元素就会出现在先绘制的元素上。

通常情况下(即使用 CSS 定位前),该绘制顺序由元素在 HTML 中出现的源码顺序决定。以如下 HTML 标记的这三个元素为例:

html 复制代码
<div>one</div>
<div>two</div>
<div>three</div>

它们相互间的堆叠行为将如图 6.11 所示。这里使用了负的外边距来让元素重叠,但并没有设置任何定位。可以看到,源码位置靠后的元素绘制在了位置靠前的元素上:

图 6.11 正常情况下三个元素的堆叠效果

而设置定位后,情况就不同了。浏览器会优先绘制所有未被定位的元素(non-positioned elements),然后再绘制已定位的元素。默认情况下,已定位的所有元素都会出现在尚未定位的元素前面(to the front)。如图 6.12 所示,给前两个元素加上 position: relative 后,它们就绘制到前面去了,覆盖了静态定位下的第三个元素,尽管元素在 HTML 中的源码顺序并未改变。

注意,在定位的这两个元素中,第二个元素还是绘制在了第一个元素的前面。虽然定位元素都被放到了前面,但它们之间基于源码的重叠关系仍旧不变。

图 6.12 已定位的元素绘制在了静态元素的前面

也就是说,此时的示例页中,模态框和下拉菜单都会出现在静态内容之前(符合预期),但源码里后出现的元素还是会绘制到先出现的元素前面。要解决这个问题,有一种方案是将 <div class="modal"> 及其所有内容全部移动到下拉菜单 HTML 源码的后面。

通常情况下,模态框都会放到网页内容的最后,即 </body> 关闭标签的前面;大多数构建模态框的 JavaScript 库也会自动照这样处理。因为模态框用的是固定定位,所以无论其 HTML 标记在哪儿,最终都会被定位到屏幕正中。

移动源码位置这招对于固定定位元素来讲倒是没啥影响,但要是换作相对定位元素或者绝对定位元素,这招就失灵了。因为相对定位元素依赖于文档流,而绝对定位元素依赖于它最近的那个祖先定位元素(译注:即 containing block 包含块。详见 6.2 节内容)。这就需要我们另辟蹊径来控制此类元素的堆叠行为。于是就轮到 CSS 中的 z-index 属性闪亮登场了!

6.4.2 用 z-index 控制堆叠顺序 Manipulating stacking order with z-index

z-index 属性的值可以为任意整数(正负数均可)。这里的 z 表示的是笛卡尔 X-Y-Z 坐标系(译注:即三维直角坐标系)里的深度方向。z-index 值较高的元素会出现在该值较低的元素的前面。属性值为负数的元素则会出现在静态元素后面。

使用 z-index 属性便是解决页面堆叠问题的第二种方案。该方案不要求修改 HTML 的结构,只需令元素 modal-backdropz-index 值为 1、且元素 modal-bodyz-index 值为 2 即可(这样就确保了模态框的主体部分位于蒙层的前方)。根据代码清单 6.11 更新本地样式表:

代码清单 6.11 给模态框加上 z-index 使其出现在下拉菜单前面

css 复制代码
.modal-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(0 0 0 / 0.5);
  z-index: 1;  /* 将模态框的蒙层置于未设置 z-index 的元素前方 */
}

.modal-body {
  position: fixed;
  inset-block: 3em;
  inset-inline: 20%;
  padding: 2em 3em;
  background-color: white;
  overflow: auto;
  z-index: 2;  /* 将模态框主体提到蒙层的前方 */
}

z-index 看似简单,使用时却有两个小陷阱(gotchas)务必要当心:一是 z-index 只对定位元素生效,无法控制静态元素的堆叠顺序;其二,一旦给定位元素设置了 z-index,就必然会牵涉到另一个核心概念,称之为 堆叠上下文(stacking context

(上篇完。由于篇幅较长,堆叠上下文的核心概念及其作用原理将在下篇中重点介绍,敬请关注)



关于《CSS in Depth》(中译本书名《深入解析 CSS》)

第 1 版 第 2 版
读者评分 原版:4.7 (亚马逊);中文版:9.3(豆瓣) 原版:5.0(亚马逊);中文版:暂无,待出版
出版时间 原版:2018 年 3 月 ;中文版:2020 年 4 月 原版:2024 年 7 月;中文版:暂无,待出版
原价 原版:$44.99 ;中文版:¥139.00 原版:$59.99;中文版:暂无,待出版
现价 原版:$36.49 ;中文版:¥52.54 起步 原版:$52.09;中文版:暂无,待出版
原版国内预订 起步价 ¥461.00 起步价 ¥750.00

本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

相关推荐
蟾宫曲2 小时前
在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
前端·npm·vue3·vite·element-plus·计时器
秋雨凉人心2 小时前
简单发布一个npm包
前端·javascript·webpack·npm·node.js
liuxin334455662 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
qq13267029402 小时前
运行Zr.Admin项目(前端)
前端·vue2·zradmin前端·zradmin vue·运行zradmin·vue2版本zradmin
魏时烟4 小时前
css文字折行以及双端对齐实现方式
前端·css
哥谭居民00014 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
2401_882726484 小时前
低代码配置式组态软件-BY组态
前端·物联网·低代码·前端框架·编辑器·web
web130933203985 小时前
ctfshow-web入门-文件包含(web82-web86)条件竞争实现session会话文件包含
前端·github
胡西风_foxww5 小时前
【ES6复习笔记】迭代器(10)
前端·笔记·迭代器·es6·iterator
前端没钱5 小时前
探索 ES6 基础:开启 JavaScript 新篇章
前端·javascript·es6