深入了解层叠上下文和层叠顺序

1,616 阅读4分钟

前话:z-index只是CSS层叠上下文和层叠顺序中的一个马仔

1. 层叠上下文 stacking context

当元素具有了层叠上下文,这个元素在z轴上就“高人一等”,离用户更近

2. 层叠水平 stacking level

  • 所有元素都有
  • 决定同一层叠上下文中的元素在z轴上的显示顺序
  • 比较两个元素的层叠水平,必须是这两个元素在同一个层叠上下文中,否则没有意义
  • z-index可以影响层叠水平(只是影响,不是决定)

3. 层叠顺序 stacking order

层叠顺序是规则(在同一个层叠上下文中的元素,对应下面规则的序号越大,位置越高)

  1. 层叠上下文 background/border
  2. 负z-index
  3. block块级元素
  4. float浮动元素
  5. inline/inline-block行内元素
  6. z-index:auto或者z-index:0(不依赖z-index的层叠上下文 看6.3)
  7. 正z-index

1通常是装饰属性;34是布局,5是内容——所以行内元素具有较高的层叠序号

4. 务必牢记的层叠准则

  1. 谁大谁上:具有明显的层叠水平标识的时候(如z-index),层叠水平高的元素在上面(官大的压死官小的)

  2. 后来居上:层叠水平一致、层叠顺序相同时,DOM流后面的元素会覆盖前面的元素(长江后浪)

5. 层叠上下文的特性(尽情把它当成一个特殊元素)

  1. 层叠上下文的层叠水平比普通元素高
  2. 层叠上下文可以阻断元素的混合模式
  3. 层叠上下文可以嵌套,内部层叠上下文及其子元素均受制于外部的层叠上下文
  4. 层叠上下文和兄弟元素相互独立
  5. 每个层叠上下文自成体系,不同层叠上下文元素发生重叠的时候,以父级层叠上下文的层叠顺序决定层叠水平

6. 创建层叠上下文

  1. 页面根元素具有层叠上下文——根层叠上下文

  2. z-index:int 的定位元素

    position:relative || absolute || fixed;声明的定位元素,当z-index不是auto的时候,会创建层叠上下文

    举栗子:定位元素divz-index:auto,是普通元素,则内部元素就按z-index大小决定层叠顺序;但是当z-index: 0,div就是层叠上下文元素。特性5和“后来居上”的准则作用下img的index失效。

  3. 其他CSS3属性

    1. z-index不为auto的flex-item

      • 条件1:父级需要是flex/inline-flex
      • 条件2:子元素z-index不为auto

        满足上面两个条件的flex-item成为层叠上下文元素。看栗子

    2. opacity值不为1

      半透明元素具有层叠上下文 后面几个属性的例子都在这里哟

    3. transform不是none

    4. mix-blend-mode不是normal

      类似于PS的混合模式

    5. filter不是none

    6. isolation:isolate

      isolation是为mix-blend-mode而生的属性;mix-blend-mode混合默认z轴所有层叠在下面的元素,例子中box也被混合了。但是加上isolation:isolate,box就具有层叠上下文,层叠水平变高,不被混合

    7. will-changed指定的属性值为上面任意一个

      will-change是提高页面滚动、动画等渲染性能的属性 了解一下

    8. -webkit-overflow-scrolling:touch

      CSS3针对iOS的新属性,激活iOS平滑滚动

7. 层叠上下文与层叠顺序

  1. 一旦普通元素具有层叠上下文,层叠顺序就会变高。其顺序要分两种情况:

    1. 层叠上下文元素不依赖z-index数值,可以看作z-index:auto或者z-index:0,排在正z-index后面
    2. 层叠上下文元素依赖z-index数值,则由数值决定
  2. 定位元素层叠在普通元素之上,因为一旦成为定位元素,z-index自动生效,默认z-index:auto也可以看作z-index:0;所以会覆盖block、inline、float元素

  3. 层叠上下文元素的层叠顺序是z-index:auto级别

     <img id="img1" src="" style="transform:scale(1);">
     <img id="img2" src="" style="position:relative">

    上面两个图片,img1是层叠上下文元素层叠顺序是z-index:auto,img2是定位元素z-index:auto;所以根据DOM流的位置决定了层叠表现,“后来居上”。

解决问题

做用户留存表格,需要实现鼠标hover时所在列和行高亮呈现十字效果。参考网上的代码发现高亮有问题:鼠标只能往下移动或者左右移动,不能向上移动。

简化代码看栗子

  • 原因:在::after伪元素还没有加z-index的时候,由于“后来居上”的渲染层叠顺序,::after之前的DOM元素在其宽高之内的会被覆盖
  • 解决:在table加transform:scale(1)触发table具有层叠上下文;在::after加z-index: -1

根据层叠顺序,负z-index元素 > 层叠上下文。

所以伪元素可以被用户看见但又不至于阻止鼠标的hover行为。(nice)

参考

segmentfault row_and_column_highlight

深入理解CSS中的层叠上下文和层叠顺序——张鑫旭