我理解的层叠上下文

236 阅读4分钟

1. 概念

我们假定用户正面向(浏览器)视窗或网页,而 HTML 元素沿着其相对于用户的一条虚构的 z 轴排开,层叠上下文就是对这些 HTML 元素的一个三维构想。众 HTML 元素基于其元素属性按照优先级顺序占据这个空间。

2. 元素默认的层叠上下文顺序

When the z-index property is not specified on any element, elements are stacked in the
following order (from bottom to top - 层叠顺序从下至上)
1. The background and borders of the root element - 根节点是第一个层叠上下文元素
2. Descendant non-positioned blocks, in order of appearance in the HTML - 后代没有设置 positioned 顺序排列
3. Descendant positioned elements, in order of appearance in the HTML - 后代设置 positioned 的元素顺序排列

3. 使用 z-index 修改层叠上下文

The z-index property can be specified with an integer value (positive, zero, or 
negative), which represents the position of the element along the z-axis. If you 
are not familiar with the z-axis, imagine the page as a stack of layers, each one 
having a number. Layers are rendered in numerical order, with larger numbers above 
smaller numbers.

解释: 
我们看到的屏幕是元素按照一定规则在 z 轴排序的层叠图, z-index 属性值为整数, 只有 positioned 元素
才能生效, 并且 z-index 大的叠在 z-index 小的元素上面.

3. 哪些属性可以让标签形成一个层叠上下文的特殊属

  • 文档根元素(html);

  • position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;

  • position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);flex (

  • flexbox 容器的子元素,且 z-index 值不为 auto;

  • grid 容器的子元素,且 z-index 值不为 auto;

  • opacity 属性值小于 1 的元素(参见 the specification for opacity);

  • mix-blend-mode 属性值不为 normal 的元素;以下任意属性值不为 none 的元素:

  • isolation 属性值为 isolate 的元素;

  • -webkit-overflow-scrolling 属性值为 touch 的元素;

  • will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素(参考这篇文章);

  • contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。

4. 案例

案例一:

代码结构:
两并列 div 父级都设置了relative, 但都没有设置z-index, 每个父级内都有一个一个div子元素, 并设置了
absolute, 第一个父级的子元素z-inex = 1, 第二个的z-index4

展示样式: 第二个父级的子元素在最上面, 之后是第一个父级的子元素, 最下面是两个父级

分析: 
父级只设置了relative, 没设置z-index, 代表着这两个父级不会创建层叠上下文, 只有两个子级跟html元素
有层叠上下文

树形结构:
root 
    子级1 z-index 1    
    子级2 z-index 4

url链接: https://codesandbox.io/s/nervous-banzai-sxiu8u?file=/src/App.vue

案例二:

代码结构: 
两并列div都设置了relative, 第一个没有设置z-index, 第二个设置z-index1, 每个div内都有一个一个
div子元素, 并且都设置了absolute, 第一个子级设置z-index2, 第二个设置为4

展示样式: 第一个子级在最上面, 第二个子集在第二个父级上面

分析: 因为第一个父级没有设置z-index, 所以它不会创建层叠上下文

树形结构:
root(html)
    第一个子级 z-index 2
    第二个父级 z-index 1 
        第二个子级 z-index 4

url链接: https://codesandbox.io/s/wonderful-http-qg6y36?file=/src/App.vue

案例三:

代码结构:
一级菜单div有四个并列, 都设置了relative, 第一个一级菜单下面有两个都设置了absolute, z-index 为
1的二级菜单, 第一个二级菜单下面有多个三级菜单都设置了relative, z-index 为10.

展示样式:
    第一个一级菜单下面的第二个二级菜单覆盖在第一个二级菜单上面

分析:
    因为二级菜单的 z-index 一样,后面的会覆盖上面的, 三级菜单在第一个二级菜单内部, 所以层级最高也是
它的父级

树形结构:
    root(html)
       二级菜单子级
            三级菜单    
       二级菜单子级

url链接: