堆叠上下文

  本文试着先解释一下堆叠顺序是什么,在引入堆叠上下文。

  MDN上这样解释堆叠上下文:

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

  平时我们浏览网页时,可以理解为从网页的正视图方向观看,理解堆叠上下文时,我们试着从侧视图的方向理解。方方老师说CSS的一个很重要的学习方法就是实验法,本文试着将所有的结论都有实验的依据。(祝福我吧,希望可以不看回放。。。)

  首先,我们先思考一下,border和background的先后关系:

<body>
  <div class="demo"></div>
</body>

<style>
    .demo{
      width: 100px;
      height: 100px;
      border: 10px solid rgba(255,0,0,0.5);
      background: green;
    }
</style>

  效果图:

  

  可见,background < border;接着,我们在父元素里加一个div,观察一下border和子元素div的关系:

  

<body>
  <div class="parent">
    <div class="child"></div>
  </div>
</body>

<style>
    .parent{
      width: 100px;
      height: 100px;
      border: 10px solid red;
    }
    .child{
      width: 30px;
      height: 30px;
      background: blue;
      margin-left: -5px;
    }
</style>

  效果:

  

  由此得出,border<子元素块级元素div,如果元素浮动起来呢?

  

<body>
  <div class="parent">
    <div class="child"></div>
    <div class="float"></div>
  </div>
</body>

<style>
    .parent{
      width: 100px;
      height: 100px;
      border: 10px solid red;
    }
    .child{
      width: 30px;
      height: 30px;
      background: blue;
    }
    .float{
      width: 40px;
      height: 40px;
      background: rgba(0,255,0,0.7);
      float: left;
      margin-top: -10px;
    }
</style>

  效果:

  

  浮动元素在块级元素div之上,那么内联元素捏,是不是也会被浮动元素盖住?在上面的代码中加入span元素。

<span class="inline">你好</span>

span{
      margin-left: -10px;
}

  效果:

  

  所以内联元素在浮动元素之上,到现在我们的顺序是这样的,background<border<div<float<inline(内联)。

  在说浮动元素时,我们经常说这样一句话:浮动元素脱离文档流,还有一种元素也脱离文档流,那就是定位的元素,例如:相对/绝对定位。

  

<div class="relative"></div>

span{
      margin-left: -20px;
}
.relative{
      width: 30px;
      height: 30px;
      background: orange;
      position: relative;
      margin-top: -15px;
}

  效果:

  

  相对定位的元素将在浮动元素上面的内联元素盖住了,所以内联元素<相对定位元素。两个性质相同的元素,后出现的会覆盖先出现的元素,例如:

  

<div class="relative"></div>
<div class="absolute"></div>

.relative{
      width: 30px;
      height: 30px;
      background: orange;
      position: absolute;
}
.absolute{
      width: 40px;
      height: 40px;
      background: rgba(0,0,0,0.5);
      position: absolute;
}

  效果图:

  

  黑色背景的div把黄色背景的覆盖住了,但是如果我们把黄色背景的z-index设置一个除了0和auto的正值,就会有改变:

  给.relative类加上这样一句话:z-index: 1;效果如下:

  

  当z-index的值为负数时,会出现在哪呢?

  

<div class="parent">
    <div class="relative"></div>
    <div class="absolute"></div>
</div>

<style>
    .parent{
      width: 100px;
      height: 100px;
      border: 10px solid red;
      position: relative;
      background: green;
    }
    .relative{
      width: 30px;
      height: 30px;
      background: orange;
      position: absolute;
      left: 50px;
    }
    .absolute{
      width: 40px;
      height: 40px;
      background: black;
      position: absolute;
    }
</style>

  现在的效果是:

  

  当把黄色部分的设置z-index: -1时,同时把父子元素的背景设置为半透明的,效果变成了:

  

  说明,当z-index的值为负数时,是在background的后面的;

  综上,z-index<0  ==> background ==> border ==> div ==> 浮动元素 ==> 内联元素 ==> 定位元素 ==> z-index>0,以上8层。

  如果我们把position: relative的父元素设置z-index: -1,会发现子元素中z-index: -1的元素跑到了background上面,但是在div的下面。

<div class="parent">
    <div class="child"></div>
    <div class="relative"></div>
    <div class="absolute"></div>
</div>

<style>
    .parent{
      width: 100px;
      height: 100px;
      border: 10px solid red;
      position: relative;
      background: rgba(0,255,0,0.5);
      z-index: 0;
    }
    .child{
      width: 40px;
      height: 40px;
      background: rgba(30,30,230,0.5);
    }
    .relative{
      width: 30px;
      height: 30px;
      background: orange;
      position: absolute;
      left: 30px;
      top: 10px;
      z-index: -1;
    }
    .absolute{
      width: 40px;
      height: 40px;
      background: black;
      position: absolute;
    }
</style>

  效果:

  

  这是为什么呢,我们就这样从堆叠顺序的介绍过渡到堆叠上下文的概念,不生硬对吧。。。

  因为position: relative 和 z-index不为auto形成了堆叠上下文,所以,类relative这个元素应该在parent形成的堆叠上下文里面。

  mdn上列出了一下几种情况形成堆叠上下文:

  • 根元素 (HTML),
  • z-index 值不为 "auto"的 绝对/相对定位,
  • 一个 z-index 值不为 "auto"的 flex 项目 (flex item),即:父元素 display: flex|inline-flex,
  • opacity 属性值小于 1 的元素(参考 the specification for opacity),
  • transform 属性值不为 "none"的元素,
  • mix-blend-mode 属性值不为 "normal"的元素,
  • filter值不为“none”的元素,
  • perspective值不为“none”的元素,
  • isolation 属性被设置为 "isolate"的元素,
  • position: fixed
  • 在 will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值(参考 这篇文章
  • -webkit-overflow-scrolling 属性被设置 "touch"的元素

 

 

  

 

posted @ 2018-01-15 23:00  程澄  阅读(824)  评论(0编辑  收藏  举报