【CSS in Depth 2 精译_042】6.4 CSS 中的堆叠上下文与 z-index(下)——深入理解堆叠上下文

news2024/12/23 4:23:58

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

  • 第一章 层叠、优先级与继承(已完结)
  • 第二章 相对单位(已完结)
  • 第三章 文档流与盒模型(已完结)
  • 第四章 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.5 粘性定位(精译中 ⏳)
    • 6.6 本章小结

文章目录

      • 6.4.3 深入理解堆叠上下文 Understanding stacking contexts

《CSS in Depth》新版封面

《CSS in Depth》新版封面

译者按
在 6.4 节的上篇,我们用 z-index 轻松处理了下拉菜单挡住模态对话框的问题。接下来的下篇将带您深入了解堆叠上下文的相关概念。其实按照二八定律,这块内容是很多前端大牛口中的“仅作了解”的知识点;对此我持保留意见。他们这么说,无非是以过来人的身份提前剧透。但仅作了解的真正含义,我认为应该是先啃下这块硬骨头:弄清核心概念、基本原理、适用场景,以便今后能快速切入。前端要了解的知识点确实不少,但能否将遇到的陌生知识点转化为您真正的“基础知识”,前期的勤学苦练是半点都不能马虎的。一旦第一次学没彻底搞懂,后面再学难度就会明显增大,因为之前那些错误的理解会在最要紧的关头冷不丁跳出来扰乱视听,以致于行差踏错,功败垂成。在开发圈子混久了慢慢就会明白一个道理:出来混,迟早是要还的。

6.4.3 深入理解堆叠上下文 Understanding stacking contexts

所谓的 堆叠上下文(stacking contexts,是由浏览器一同绘制(painted together)的一个或多个元素组成。其中的一个元素会作为堆叠上下文的根元素(root)。比如,当给一个已设置定位的元素加上 z-index 时,它就成了该堆叠上下文的根元素;其所有后代元素则相应变为该堆叠上下文的一部分。

事实上,将堆叠上下文里的所有元素一同绘制会造成严重的后果:堆叠上下文以外的元素将永远无法叠放在该上下文内部的任意两个元素之间。也就是说,如果一个元素叠放在了某个堆叠上下文的前面,那么该元素将不会被后方堆叠上下文里任一元素所覆盖;同理,如果一个元素被放在了堆叠上下文的后面,那它将永无翻身之日,堆叠上下文中的任一元素无论怎么设置都不会让该元素挡在前面。

这么说可能有点绕,下面结合一个最简单的应用场景来演示说明。新建一个 HTML 页面,并按照代码清单 6.12 给出的 HTML 标记更新页面:

图 6.12 堆叠上下文示例 HTML 标记

<div class="box one positioned">
  one
  <div class="absolute">nested</div>
</div>
<div class="box two positioned">two</div>
<div class="box three">three</div>

这段代码包含三个内容盒子,其中有两个被设置为定位元素,其 z-index 的值均为 1;而位于第一个定位元素中的绝对定位元素,其 z-index 的值为 100。虽然后者的属性值很大,但最终还是被渲染到了第二定位元素的后面,只因其父元素(即第一个定位元素)形成的堆叠上下文位于第二个内容盒的 后方(如图 6.13 所示)。

图 6.13 整个堆叠上下文相对于页面上其他元素进行叠放

【图 6.13 整个堆叠上下文相对于页面上其他元素进行叠放】

上述效果的 CSS 样式如代码清单 6.10 所示。将它们更新到本地页面。其中大部分样式用于设置尺寸大小与颜色,以便区分堆叠顺序。元素间的重叠效果还是用负的外边距实现。当中最核心的代码,莫过于给每个元素设置 positionz-index 的部分了:

代码清单 6.13 创建堆叠上下文的样式代码

body {
  margin: 40px;
}
 
.box {
  display: inline-block;
  width: 200px;
  line-height: 200px;
  text-align: center;
  border: 2px solid black;
  background-color: #ea5;
  margin-left: -60px;  /* 实现元素重叠效果 */
  vertical-align: top;
}
 
.one { margin-left: 0; }
.two { margin-top: 30px; }
.three { margin-top: 60px; }

/* 每个定位元素都分别创建了一个 z-index 值为 1 的堆叠上下文 */
.positioned {
  position: relative;
  background-color: #5ae;
  z-index: 1;
}
 
.absolute {
  position: absolute;
  top: 1em;
  right: 1em;
  background-color: #fff;
  border: 2px dashed #888;
  z-index: 100;  /* z-index 只对该元素所在的堆叠上下文中的堆叠顺序生效 */
  line-height: initial;
  padding: 1em;
}

根据堆叠上下文的相关概念,叠放在第二个盒子下面的第一个盒子其实是它所在堆叠上下文的根元素。正因如此,即便当中的绝对定位元素给到一个很高的 z-index 值,依旧无法覆盖在第二个盒子上面。大家不妨在浏览器的开发者工具里试验一下,以便更好地理解这种堆叠关系。试着改改每个元素的 z-index 值,看看效果究竟如何。

注意

添加 z-index 值并非创建堆叠上下文的唯一途径,比如 opacity 属性,在属性值小于 1 时也能创建,类似的属性还有 transformfilter 等等。此外,固定定位和粘性定位(sticky positioning,将在本章 6.5 节介绍)即便不指定 z-index 值也能创建一个堆叠上下文。而 HTML 文档的根节点(document root,即 <html> 元素)则会为整个页面创建一个 顶级堆叠上下文(top-level stacking context)

堆叠上下文中的所有元素会按照以下顺序,从后往前依次叠放:

  • 堆叠上下文的根元素;
  • z-index 为负值的定位元素,及其子元素;
  • 非定位(Non-positioned)元素;
  • z-index 值为 auto 的定位元素,及其子元素;
  • z-index 为正值的定位元素,及其子元素。

用变量来跟踪 z-index 的值

如果不根据页面各组件的优先级划分出条理清晰的堆叠顺序,那么页面样式表很容易演变为一场 z-index 混战。没有清晰的说明,开发人员在给一个模态框之类的元素设计样式时,为了防止被其他元素遮挡,很可能会指定一个高得离谱的 z-index,比如 999999。像这样反复折腾几遍后,后续给新组件指定 z-index 值就只能凭感觉和运气了。

为避免情况失控,可以使用 CSS 的自定义属性(custom properties,详见第 2 章 2.6 节相关内容)来统一管理:将所有 z-index 值定义为变量并放到同一个地方集中管理(如下所示)。这样就能一目了然地看出那些元素在前、那些元素在后了:

--z-loading-indicator: 100;
--z-nav-menu:          200;
--z-dropdown-menu:     300;
--z-modal-backdrop:    400;
--z-modal-body:        410;

步长增量建议预留为 10 或者 100,以便今后根据实际情况进行增补。

要是发现 z-index 的行为不符合预期,记得在 DOM 数中定位到该元素的祖先节点,直至锁定堆叠上下文的根节点;然后调整其 z-index 属性,将整个堆叠上下文前移或后置。此外,遇到多个堆叠上下文相互嵌套的情况,操作时务必慎之又慎。

当页面很复杂时,可能很难准确判断是哪个堆叠上下文出的问题。因此,在创建之初就得多加小心,防患于未然。没有特殊理由最后不要随意创建堆叠上下文,尤其是遇到元素包含了很大一块内容的时候,这一点尤为重要。再者,要尽量将模态框这样的独立定位元素放到 DOM 结构的最外层、紧邻关闭标签 </body> 之前,这样一来就没有什么外部的堆叠上下文能束缚住它们了。

一些开发人员会忍不住给页面大量元素设置定位。一定要克制这种冲动。定位用得越多,网页就越复杂,也就越难以调试。如果已经定位了大量元素,不妨回过头来重新评估一下当前的状况,尤其是当发现自己很难调试出想要的效果时,一定要反思。如果可以用别的方案实现当前的布局效果,应当优先选用那些方案。

相比手动设置定位来实现某个布局,如何能够依靠文档流实现同样的效果,那么浏览器会帮我们处理好很多边界情况。切记:CSS 定位会让元素移出文档流(positioning takes elements out of the document flow)。一般来说,只有在需要将元素叠放到其他元素之前时,才会考虑 CSS 定位。



关于《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 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

聊聊国内首台重大技术装备(2)

上次&#xff0c;介绍了《首台&#xff08;套&#xff09;重大技术装备推广应用指导目录&#xff08;2024年版&#xff09;》中介绍的硅外延炉&#xff0c;湿法清洗机&#xff0c;氧化炉&#xff0c;见文章&#xff1a; 《聊聊国内首台重大技术装备&#xff08;1&#xff09;》…

ESP32微信小程序SmartConfig配网

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ESP32&微信小程序SmartConfig配网 前言一、SmartConfig是什么&#xff1f;二、使用乐鑫官方的smart_config例子1.运行照片 三、微信小程序总结 前言 本人是酷爱ESP32S3这…

数据结构--包装类简单认识泛型

目录 1 包装类 1.1 基本数据类型和对应的包装类 1.2 装箱和拆箱&#xff0c;自动装箱和自动拆箱 2 什么是泛型 3 引出泛型 3.1 语法 4 泛型类的使用 4.1 语法 4.2 示例 5 泛型的上界 5.1 语法 5.2 示例 5.3 复杂示例 8 泛型方法 8.1 定义语法 8.2 示例 总结 1 …

【web安全】——XSS漏洞

1.XSS漏洞基础 1.1.漏洞成因 XSS(Cross-site scripting)被称为跨站脚本攻击&#xff0c;由于与层叠样式表的缩写一样&#xff0c;因此被缩写为XSS.XSS漏洞形成的原因是网站/程序对前端用户的输入过滤不严格&#xff0c;导致攻击者可以将恶意的is/html代码注入到网页中&#x…

LeetCode[中等] 763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。 注意&#xff0c;划分结果需要满足&#xff1a;将所有划分结果按顺序连接&#xff0c;得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度的列表。 思路 贪心…

JavaWeb酒店管理系统(详细版)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

QT 界面编程中使用协程

QT 界面编程中使用协程 一、概述二、集成2.1、编译 Acl2.2、将 Acl 库集成到 QT 项目中2.3、开始编写代码2.3.1、QT 程序初始化时初始化 Acl 协程2.3.2、在界面中创建协程2.3.3、界面程序退出前需要停止协程调度2.3.4、在界面线程中下载数据2.3.5、在协程中延迟创建窗口 2.4、效…

8642 快速排序

### 思路 快速排序是一种分治算法&#xff0c;通过选择一个基准元素将数组分成两部分&#xff0c;然后递归地对每部分进行排序。每次分区后输出当前排序结果。 ### 伪代码 1. 读取输入的待排序关键字个数n。 2. 读取n个待排序关键字并存储在数组中。 3. 对数组进行快速排序&am…

HarmonyOS/OpenHarmony 自定义弹窗页面级层级控制解决方案

关键词&#xff1a;CuntomDialog自定义弹窗、SubWindow子窗口、页面级、弹窗层级控制、鸿蒙、弹窗展示层级异常 问题存在API版本&#xff1a;API10 - API12&#xff08;该问题已反馈&#xff0c;期望后续官方能增加页面级控制能力&#xff09; 在正常的鸿蒙app开发过程中&…

【Linux】命令管道

一、命名管道的介绍 之前的管道博客中介绍的是匿名管道&#xff0c;这个管道的应用的一个限制就是只能在具有公共祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。 如果我们不想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作&#xff0c;他经常…

Arduino UNO R3自学笔记6 之 Arduino引脚(IO)功能介绍

注意&#xff1a;学习和写作过程中&#xff0c;部分资料搜集于互联网&#xff0c;如有侵权请联系删除。 前言&#xff1a;Ardunio UNO R3有很多引脚&#xff0c;接下来主要介绍它们都可以用做什么。 从上图不难看出开发板引脚也不是有多少&#xff0c;分类来看也就以下种类型&…

C语言、Eazy_X——五子棋

//五子棋#include<graphics.h>#define board_size 20 #define pixel 600 int pr pixel / board_size; char board_data[board_size][board_size]; char current_piece o; int count 0;//检测指定玩家是否获胜 bool CheckWin(char c) {int i, j;//检查行for (i 0; i &…

位运算(6)_只出现一次的数字 II

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 位运算(6)_只出现一次的数字 II 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 …

自动驾驶系列—解析自动驾驶汽车的“大脑”:电子电气架构详解与选型指南

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

【折半查找】

目录 一. 折半查找的概念二. 折半查找的过程三. 折半查找的代码实现四. 折半查找的性能分析 \quad 一. 折半查找的概念 \quad 必须有序 \quad 二. 折半查找的过程 \quad \quad 三. 折半查找的代码实现 \quad 背下来 \quad 四. 折半查找的性能分析 \quad 记住 比较的是层数 …

python如何显示数组

np.set_printoptions方法的相关属性&#xff1a; <span style"background-color:#272822"><span style"color:#f8f8d4">set_printoptions(precisionNone, thresholdNone, edgeitemsNone, linewidthNone, suppressNone, nanstrNone, infstrNo…

【论文精度——长尾问题】Long-Tailed Learning as Multi-Objective Optimization

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;论文精读_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. Abstract …

Python数据分析篇--NumPy--进阶

人有一种天生的、难以遏制的欲望&#xff0c;那就是在理解之前就评判。 -- 米兰昆德拉 多维数组 1. 一维数组只有行&#xff0c;二维数组相比一维数组多了列这个维度&#xff0c;而三维数组则类似多个二维数组堆叠在一起&#xff0c;形如一个立方体。 二维数组的创建 1. 二…

Java中的顺序控制、分支控制、嵌套分支if-else

if-else 顺序控制分支控制if-else单分支1.基本语法2.说明&#xff1a;3.案例说明4.流程图 双分支1.基本语法2.说明&#xff1a;3.案例说明4.流程图5.练习 多分支1.基本语法2.说明&#xff1a;3.流程图4.练习 嵌套分支1.基本介绍2.基本语法3.练习 顺序控制 1.介绍&#xff1a;程…

CMake所学

向大佬lyf学习&#xff0c;先把其8服务器中所授fine 文章目录 前言一、CMakeList.txt 命令1.1 最外层CMakeLists1.1.1 cmake_minimum_required&#xff08;&#xff09;1.1.2 project&#xff08;&#xff09;1.1.3 set&#xff08;&#xff09;1.1.4 add_subdirectory&#xf…