51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

css层叠

前言 {#前言}

在前端开发中你一定用过z-index,它用于让某些元素在视觉上更接近用户,但是有时你又会发现它没有用了,这是因为z-index只是css层叠规则中的一部分,它的起效需要其他css的作用,下面我们就来简单聊聊css层叠这部分的知识,让你不再只是会乱用z-index。

什么是层叠上下文(stacking context) {#什么是层叠上下文(stacking-context)}

这里用一下MDN的定义


翻译过来就是: 层叠上下文是HTML元素的三维概念,这些HTML元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的z轴上延伸,HTML元素依据其自身属性按照优先级顺序占用层叠上下文的空间。

当然这么直接搬文档大部分人一开始肯定是看不懂的,我们可以这么理解,层叠上下文是一个有很多层的盒子,盒子里面有很多书(HTML元素),这些书会根据他们设置的CSS样式摆放在不同的层上,所以我们可以把层叠上下文理解成是一个分层的大容器(虽然这么理解不完全正确)

如何产生层叠上下文 {#如何产生层叠上下文}

这是MDN说明的可以产生层叠上下文的情况

然后我们翻译一下

  1. 文档的根元素(HTML元素)
  2. 设置z-index为非auto值的绝对定位和相对定位元素
  3. 设置了position为fixed或者sticky的元素
  4. 父元素设置了display:flex,同时自身设置了z-index为非auto值的元素
  5. opacity小于1的元素
  6. z-index非auto的网格布局(gird)子元素
  7. mix-blend-mode属性值不是normal的元素
  8. 下面这些属性值任意一个不是none的元素
    • transform
    • filter
    • perspective
    • clip-path
    • mask/mask-image/mask-border
  9. isolation为isolate值为的元素
  10. -webkit-overflow-scrolling值为touch的元素
  11. will-change为非初始值的元素
  12. contain属性为layout,paint,strict,content的元素

当然你不需要全部记下来,其实记住前六点应该差不多了

再来聊聊层叠等级(stacking level) 和 层叠顺序(stacking order) {#再来聊聊层叠等级(stacking-level)-和-层叠顺序(stacking-order)}

你如果之前看过其他的文章,你就会发现这里我和他们对stacking level的翻译不大一样,其实我一直觉得层叠水平多少有点歧义和不够容易理解,所以我就在这里使用层叠等级这个翻译,其实老实说我并不想放入这两个名词,因为没有必要反而容易混淆,不过最后还是放上来了,因为考虑到有些朋友可能是看过其他博客才来的,怕没有这两个东西不习惯(划掉)

其实层叠等级和层叠顺序在官方文档中没有明确的定义(有可能有,但我没找到),他们只是文档中层叠上下文中用法中偶尔出现了几次的名词,所以我就用自己的理解来下定义了

层叠等级:每一个元素都在包含他的那个层叠上下文中有一个等级,这个等级级就叫做层叠等级,当元素发生重叠时,层叠等级越高,离用户越近,层叠等级小的会被盖住,你还需要注意以下的几点

1. 一个元素只能有一个层叠等级,因为它只能属于一个层叠上下文,就像一本书只能属于一个盒子
2. 一个元素的层叠等级只在它属于的层叠上下文中生效,就像一本书属于一个盒子,他不能跑出这个盒子单独排序

层叠顺序:层叠顺序是一种z轴上的排序规则,这个规则是:同一个层叠上下文中层叠等级高的优先级较高,即层叠等级越高,离用户越近

看看层叠等级有多少级 {#看看层叠等级有多少级}

又到了我们熟悉的丢文档的时间,这是CSS规范2018有关层叠等级的说明

翻译一下:

在一个层叠上下文A中,分层如下(层叠等级逐渐提高):

  1. 层叠上下文A的背景和边框
  2. 在这个层叠上下文A中生成了层叠上下文B且z-index为负值的元素
  3. 常规流非定位块盒
  4. 非定位的浮动盒子
  5. 常规流非定位行盒(注意,这里的行盒包括display为inline的元素和inline-bloc的k元素)
  6. 这一条有三点
    • 生成了堆叠上下文且z-index为0的元素
    • z-index为auto的定位元素
    • 某些不需要设置z-index为数值就能生成堆叠上下文的元素(主要是CSS3新增的)
  7. z-index为正值的堆叠上下文B

在一个层叠上下文中,层叠等级越高的,离用户越近,如果层叠等级相同,源代码中后面的元素会覆盖前面的元素
概括起来就是谁大谁上,后来居上

看几个例子 {#看几个例子}

例子一 {#例子一}

估计看了这么多的理论知识,不少人是一脸懵逼的,我们在这里就综合一下,用几个例子来运用前面的知识

HTML

|------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <body> <div id="box1"> box1:我是z-index为负值的堆叠上下文 </div> <div id="box2"> box2:我是普通块盒 </div> <div id="box3"> box3:我设置了浮动 </div> <div id="box4"> box4:我是行块盒 </div> <div id="box5"> box5:我是定位元素,z-index为0,在蓝色盒子的前面 </div> <div id="box6"> box6:我是定位元素,z-index为auto </div> <div id="box7"> box7:我是定位元素,z-index为0,在蓝色盒子的后面 </div> <div id="box8"> box8:我是z-index为正值的堆叠上下文 </div> </body> |

CSS

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | div { width: 150px; height: 150px; box-sizing: border-box; padding: 0 30px; } #box1 { background-color: orange; position: relative; z-index: -1; margin-top: 0px; } #box2 { background-color: yellow; margin-top: -60px; } #box3 { background-color: green; float: left; margin-top: -80px; } #box4 { background-color: #00bbff; display: inline-block; margin-top: 0px; margin-left: -150px; } #box6 { background-color: blue; position: relative; margin-top: 0px; top: -80px; z-index: auto; } #box5 { position: absolute; background-color: #4cae4c; z-index: 0; top: 320px; left: 96px; } #box7 { position: absolute; background-color: pink; z-index: 0; top: 320px; left: 328px; } #box8 { background-color: purple; position: relative; z-index: 1; margin-top: 0px; top: -140px; } |

结果


在这个文档中,一共有5个元素产生了层叠上下文,分别是html元素,box1,box5,box7,box8,
html元素产生的堆叠上下文中有8个元素(box1 - box8),这8个box元素有他们对应的层叠等级(具体的等级参照上面),
层叠等级越高,离用户越近,层叠等级低的元素被盖住,然后层叠等级相同的(比如5,6,7),按照源文件中的先后顺序覆盖

例子二 {#例子二}

现在我们加大难度,把html文件改一下,在box5和box7中分别加一个元素
css不变

|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <div id="box1"> box1:我是z-index为负值的堆叠上下文 </div> <div id="box2"> box2:我是普通块盒 </div> <div id="box3"> box3:我设置了浮动 </div> <div id="box4"> box4:我是行块盒 </div> <div id="box5"> box5:我是定位元素,z-index为0,在蓝色盒子的前面 <div style="position: absolute; z-index: 2; background-color: #8a6d3b; top: 97px; left: 0px"> 我是在box5里面的box5-1,z-index为2,绝对定位 </div> </div> <div id="box6"> box6:我是定位元素,z-index为auto </div> <div id="box7"> box7:我是定位元素,z-index为0,在蓝色盒子的后面 <div style="position: absolute; z-index: -1; background-color: #FF5B17; top: 101px; left: -2px"> 我是在box6里面的box7-1,z-index为-1,绝对定位 </div> </div> <div id="box8"> box8:我是z-index为正值的堆叠上下文 </div> |

然后看起来匪夷所思的事情发生了

z-index比较大的元素居然在z-index较小的元素下面,这是为什么呢,我们来分析一波,首先最外面的层叠上下文依旧是html元素,
html层叠上下文中有box1 - box8一共8个元素,其中box5和box7因为设置了z-index为0和定位,box5和box7 分别形成了新的层叠上下文,
box5-1和box7-1分别在box5和box7形成的层叠上下文中,box5-1和box7-1设置的z-index只在他们所属的层叠上下文中生效,而他们两个根本不在一个层叠上下文中,所以z-index不能影响他们的覆盖关系,影响他们覆盖关系的是他们所属的层叠上下文,因为box5和box7在html形成的层叠上下文中是box7覆盖box5,所以box7层叠上下文和它层叠上下文中所有的元素都比box5层叠上下文中的元素里用户近,所以box7-1会覆盖box5-1

可以举个形象点的例子,层叠上下文相当于大箱子,没有形成层叠上下文的元素的相当于书,在html这个大箱子中,有box1,box5,box7,box8这几个箱子,box2,box3,box4,box6这几本书,他们离用户的顺序是(从远到近)box1,box2,box3,box4,box5,box6,box7,box8,而box5-1和box7-1是在box5和box7这两个箱子里面的,既然box7这个箱子本身就比box5高,所以box7中的书肯定也比box5中的书高,而box5-1和box7-1设置的z-index只是能让他们在box5和box7这两个箱子中和其他书排序时能排得更高而已

来做个小练习看看是不是掌握了 {#来做个小练习看看是不是掌握了}

现在我们在box6中加个box6-1,设置position为absolute,z-index为1,那么box6-1和box8哪个在前面?

|---------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <body> <div id="box1"> box1:我是z-index为负值的堆叠上下文 </div> <div id="box2"> box2:我是普通块盒 </div> <div id="box3"> box3:我设置了浮动 </div> <div id="box4"> box4:我是行块盒 </div> <div id="box5"> box5:我是定位元素,z-index为0,在蓝色盒子的前面 <div style="position: absolute;z-index: 2;background-color: #8a6d3b;top: 235px;left: 73px;"> 我是在box5里面的box5-1,z-index为2,绝对定位 </div> </div> <div id="box6"> box6:我是定位元素,z-index为auto <div style="position: absolute;z-index: 1;background-color: #d9534f;top: 90px;left: 127px;"> 我是box6里的box6-1,z-index为1 </div> </div> <div id="box7"> box7:我是定位元素,z-index为0,在蓝色盒子的后面 <div style="position: absolute;z-index: -1;background-color: #FF5B17;top: 236px;left: -44px;"> 我是在box6里面的box7-1,z-index为-1,绝对定位 </div> </div> <div id="box8"> box8:我是z-index为1的堆叠上下文 </div> </body> |

因为box6没有形成层叠上下文,所以box6-1也在html形成的层叠上下文中,box6-1和box8的z-index都是1,层叠等级相同,根据后来居上原则,box8会覆盖box6-1

后记 {#后记}

那么我要分享的到这里就结束了,如果我有写错的地方或者你有其他想法或者问题,欢迎在评论区留言

测试代码:链接: https://pan.baidu.com/s/1YQvBZ8AiOLQu3c9KLobz0A 提取码: sena

赞(1)
未经允许不得转载:工具盒子 » css层叠