hanyitim / Blog

博客仓库,记录一些觉得要记的东西
0 stars 0 forks source link

基于z-index重新认识“层叠上下文” #6

Open hanyitim opened 5 years ago

hanyitim commented 5 years ago

z-index 是在设置层级的时候经常会用到的一个属性,很常用,好像也觉得没什么特别,在看过一些大佬的文章之后才知道原来“世界怎么大,我的知识这么点”

疑问

  1. z-index 除了 position能使它生效之外,还有什么属性可以让他生效?
  2. 形成层叠上下文的节点,z-index就能生效(误解)。
  3. 子元素的层级就一定在父元素上面(父元素Position非static)?

下面,带着疑问去整理相关的知识点。

基本用法

当需要设计一个层级的“层级”的时候

.box1{
    position:absolute;   //非static【默认】;absolute,fixed,relative
    z-index:2
}

//可能我box2 想在box1的上面
.box2{
    postion:absolute;
    z-index:3
}

//从之前的应用上来开,在让z-index生效的情况下,z-index 的值是越大表示层级越高【兄弟元素】

可能之前在对于“层级”的一个了解仅限于此,并没有去做更多详细的了解,但是其实这只是css“层级”关系里面的冰山一角,更具体的,可能需要好好了解一下“层叠上下文”这个点。

层叠上下文是什么鬼?

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

形成层级上下文的条件有很多,例如:

从上面列出来的属性中,我试着去推断一些信息

  1. z-index 的方式是非常直接的,通过z-index 的层级数字来去确定层级关系(在zIndex生效的情况下)
  2. opacity,filter 这两个主要跟色彩的合成有关系,在不同层叠的情况下这两个属性会出现不同的结果(影响到了渲染)
  3. trnasform,本来以为只有在涉及到3d转换的时候才会形成层叠上下文,测试的结果是translate(0,0);也会,那再重新查一下trnasform的一个描述“CSStransform属性允许你旋转,缩放,倾斜或平移给定元素。这是通过修改==CSS视觉格式化模型的坐标空间==来实现的。”

谁是老大

在有多个层叠上下文盒子的情况下,遵循一下规则

  1. 在z-index生效的情况下,兄弟元素根据z-index的大小来决定谁在上面;
  2. 两个盒子都形成层叠上下文,且==z-index:auto==,的情况下,根据dom节点的顺序来决定谁在上面(后面节点大于前面节点)。
  3. 背景 < 布局 < 内容

测试

1.zIndexDemo1,测试层叠上下文跟设置position盒子的层叠关系

//html
<div class="parent">
  <div class="Box1"></div>
  <div class="Box2">
    hello world
  </div>
<div>

//css
.Box1{
  position:absolute;
  left:0;
  top:0;
  background-color:pink;
  width:100%;
  height:100px;
}
.Box2{
  width:100%;
  height:40px;
  background-color:red;
}

//此处的结果是Box2被Box1覆盖掉了。Box1脱离了文档流浮在上方

调整 css

.Box2{
  width:100%;
  height:40px;
  background-color:red;
  opacity:0.99;
}

//Box2形成层叠上下文,Box2 覆盖了 Box1;

调整html
<div class="parent">
  <div class="Box2">
    hello world
  </div>
  <div class="Box1"></div>
<div>

//Box1覆盖着Box2;

结论:在 Box1 设置了定位之后,会覆盖住Box2,但在Box2添加了opacity:0.5 形成层叠上下文之后,Box2 跟 Box1 就在同一起跑线上了,这个时候就看dom的先后顺序来觉得谁覆盖谁。

2.zIndexDemo2,测试flex子元素是否让z-inde生效

//html
<div class="parent">
  <div class="Box1"></div>
  <div class="Box2">
    hello world
  </div>
<div>

//css
.parent{
  display:flex;
}
.Box1{
  width:100px;
  height:100px;
  background-color:pink;
  z-index:2;
}
.Box2{h
  width:100px;
  height:100px;
  background-color:red;
  margin-left:-50px;
}

结论:flex子元素是可以让z-index生效的。

3.zIndexDemo3 子元素就一定在父元素(position非static)上面?

//html

<div class="parent">
  <div class="Box1"></div>
  <div class="Box2">
    hello world
  </div>
<div>

//css
.parent{
  background-color:yellow;
  padding:30px;
  position:relative;
  z-index:0;
}
.Box1{
  position:absolute;
  left:0;
  top:10px;
  background-color:pink;
  width:100%;
  height:100px;
  z-index:-1;
}
.Box2{
  width:100%;
  height:40px;
  background-color:red;
}

//Box1依然在parent上面

调整css
.parent{
  background-color:yellow;
  padding:30px;
  position:relative;
}

//去除parent的zIndex属性之后,Box1隐藏到了parent后面

调整css
.parent{
  background-color:yellow;
  padding:30px;
  position:relative;
  opacity:0.99;
}

//添加opacity:0.99 形成层叠上下文之后,Box1又无法通过zIndex负值隐藏到parent后面

调整css
.parent{
  background-color:yellow;
  padding:30px;
  position:fixed;
}

//结果与上面一致

结论:

总结

  1. 形成层叠上下文的方式有很多,更具体的看MDN的层叠上下文文档
  2. 子元素可以通过zIndex负值隐藏在父元素后面,前提是父元素不形成层叠上下文
  3. 可以让zIndex生效的不只是postion,还有其他属性
  4. 层级的覆盖
    • zIndex的大小
    • 节点先后
    • 在没有脱离文档流的情况下。形成层叠上下文的节点会覆盖没有形成层叠上下文的节点。

==备注:如果有错误的地方麻烦大佬多指点。==