z-index是最常用的CSS属性之一,前些天看一本书,发现了一些细节,将其笔记单独摘出来做一个总结。

z-index究竟是什么?

根据W3C,z-index属性用来决定:

  1. 盒子在堆叠上下文中的堆叠级别;
  2. 盒子是否建立了一个堆叠上下文。

要理解z-index,需要首先了解渲染层(rendering layer)和堆叠次序。

渲染层、堆叠次序与z-index

网页是三维结构,具有水平维度的X轴和垂直维度的Y轴,以及第三维的Z轴——一个元素的z-index属性代表了该元素所在的渲染层,即在Z轴上的位置。

默认的渲染层位于Z轴的位置0上。如果一个渲染层的z-index为负数,那么这一层将会被放置在默认渲染层的后面,用户就看不见它了(父层的背景颜色会将其遮盖)。这项技术通常被用以在开发者不希望用户看到这个元素的情况下对其进行计算。

当一个定位元素脱离了文档流,它仍然处在与之前相同的那个渲染层中。定位仅仅影响了元素在这个渲染层中的堆叠次序

默认堆叠次序

没有z-index属性的元素,按照以下顺序从底到顶依次排序:

  1. 根节点的背景和边框;
  2. 文档流中的后代元素,按照在HTML中出现的顺序;
  3. 浮动元素(关于float是否脱离标准文档流详细解析);
  4. 脱离文档流的定位后代元素,按照在HTML中出现的顺序。

See the Pen JWLjdv by testudy (@testudy) on CodePen.

重写默认堆叠次序

z-index属性被用来在定位元素上指定不同于默认情形的堆叠次序。
为元素赋一个大于0的z-index属性值,就使得元素离顶部(离用户)更近了。如果在同一个堆叠上下文中,其他元素也具有z-index属性值,那么z-index属性值最高的元素将出现在最顶部。而为元素的z-index赋一个负值,就把这个元素放在了默认渲染层的后面。具有相等z-index属性值的元素,堆叠顺序遵循默认的堆叠规则。

堆叠上下文

默认堆叠次序和z-index值生效的前提条件是,这些元素是某个已经创建堆叠上下文祖先元素的后代元素。

堆叠上下文是怎么创建的?

  1. 页面的根元素<html>创建了默认堆叠上下文;
  2. 定位元素并且具有非auto的z-index属性值;
  3. 在Webkit和Chrome 22+中,对于固定定位的元素,即使z-index为auto,也总是会创建上下文;
  4. 元素具有小于1的opacity属性;
  5. 元素中对于CSS 3中的一些属性,比如transform属性不为none,也会创建堆叠上下文。

事情越来越复杂了

影响元素层叠次序的因素:层叠上下文(stacking context)、定位、透明度等等。
堆叠上下文最重要的作用是,它创建了一组独立的渲染层,其中各元素的堆叠次序不受外部元素的z-index值影响。

See the Pen z-index by testudy (@testudy) on CodePen.

管理z-index

在商户网站之类的单一、静态Web网站中,将不同种类的控件划分为不同的层级,是一种简单有效的管理z-index的方法。比如下表中IAB显示广告z-index使用指导

z-index区间 内容类型 详情
< 0 背景元素  
0 - 4,999 主要内容与标准广告 标准广告标签与常规内容,包括OBA本身的常规消息
5,000 - 1,999,999 扩展广告 整个可扩展的广告单元应该位于该区间
2,000,000 - 2,999,999 浮动广告 页面上方的广告(OTP)
3,000,000 - 3,999,999 弹出元素 对话框,消息提示框
4,000,000 - 4,999,999 非固定元素 调查补充区域
5,000,000 - 5,999,999 扩展站点导航元素 下拉导航、站点警告等。只有导航元素的扩展部分才位于这一层
6,000,000+ 全页面浮层 覆盖整个页面(OTP)的广告,以及页面之间的覆盖整个页面的广告

但对于动态的Web应用等不确定的环境中,DOM结构和z-index会被频繁更改,更可靠的方案是:利用关于z-index的知识,在应用和组件的代码中,编程管理z-index。

z-index管理者对象

原作者创建了jenga对象来实现z-index的编程管理,主要包含一下功能:

  1. 把一个元素放到堆叠上下文的顶部或底部;
  2. 创建一个元素的堆叠上下文;
  3. 获取一个元素是否创建了堆叠上下文。

仔细思考后将其简化修改,具体参考jenga修改分析