资讯专栏INFORMATION COLUMN

CSS Stacking Context 里那些鲜为人知的坑

OldPanda / 1098人阅读

摘要:我们通过给已定位元素指定值以改变元素在其中轴的相对偏移量。这里的相对偏移指的是以为基准,相对于其它兄弟元素距离用户远近的顺序。以上便是我对中造成诸多匪夷所思现象原因的总结。目前这个仍未被解决,官方建议避免在元素下做定位。

通常我们在学习/了解CSS的时候,并不会直接接触/了解到stacking context的规则,甚至在初学的时,仅仅接触到z-index、知道可以通过z-index控制元素显示的前后顺序,却常常由此碰到各式各样匪夷所思的bug,这两天我也趟了一次z-index浑水,搞明白了z-index扯出的这一系列stacking context坑。

什么是z-index

在W3C document里对z-index的解释是:

  

The z-index attribute lets you adjust the order of the layering of objects when rendering content.
It means that CSS style rules allow you to position boxes on layers in addition to the normal rendering layer (layer 0). The Z position of each layer is expressed as an integer representing the stacking order for rendering. Greater numbers mean closer to the observer.

简言之我们通过z-index在layer 0上控制「已定位」元素的先后顺序,其值越大元素越靠近用户。#这里layer 0指代root节点即html元素

什么是Stacking Context

显然仅仅知道z-index的作用并不能解释现实中诸多怪异的CSS z-index定位表现,如同上一节中提到指代root节点的layer 0,在CSS中也可构造出与其相似的结构,这种提供z-index栈空间特性并影响子元素渲染顺序的结构,我们称之为stacking context。

怎样的CSS属性可以使element形成一个Stacking Context

满足下面规则的元素将会构造出一个 Stacking Context 结构:

root元素(html)

「已定位」元素(position: absolute or relative)且 指定z-index值非auto的元素

flex item且指定z-index值非auto的元素

opacity小于1的元素

指定transform值非none的元素

指定mix-blend-mode值非normal的元素

指定filter值非none的元素

指定isolation值为isolate的元素

==特例 mobile webkit & chrome 22+, 指定position: fixed的元素==

在will-change属性上指定值为上述列表任意属性的元素

指定-webkit-overflow-scrolling值为touch的元素

*注意除了前两条之外有如此多满足创建stacking context的条件,这也是造成诸多bug的源泉,比如opacity<1

Stacking Context有什么特性

stacking context可以嵌套

每个stacking context相对于兄弟元素是完全独立的,其内部规则不会影响到外部

每个stacking context元素都会被父stacking context当做一个元素施加stacking规则

对于一个stacking context内部的元素,如果这个元素没有形成stacking context,其z-index值是auto(但其实如果这个元素没有形成stacking context,z-index属性对这个元素的表现根本没有意义,我们可以理解为这个元素和其parent stacking context是一体的)。

我们通过给已定位元素(position: absolute or relative)指定z-index值以改变元素在其parent stacking context中Z轴的「相对偏移」量。这里的「相对偏移」指的是以parent stacking context为基准,相对于其它兄弟元素距离用户远近的顺序。

由于形成stacking context的元素其z-index属性并不对内部元素产生影响,因此其子元素以其(parent stacking context)为z-index相对基准点即z-index: auto,这些子元素的stacking context兄弟元素按照下面的远近顺序展示在屏幕:

远 ---------> 近
parent stacking context >> z-index < 0 >> 非stacking context元素(z-index: auto) >> z-index >= 0

*注意在stacking context中的元素不会远于parent stacking context

非「定位」元素Stacking Context的特殊规则

先上一段极其容易产生困惑的代码(不支持embedded scripts略卵疼):

See the Pen yNJRKX by abruzzi (@abruzzi) on CodePen.


http://codepen.io/abruzzi/pen/yNJRKX

如上文提及,这里box3和box5通过opacity: .99创建了一个stacking context,但box3却覆盖在了box4之上,翻查W3C文档并没有这样一条规则定义stacking context元素默认在非stacking context元素之上;我们修改了box5的z-index属性为负值,box5依然在box6之上;我们又通过position: relative & z-index: -1创建了box7的stacking context,其表现却是正常的(话说回来,z-index: auto本身也无法形成stacking context,因此根本没有存在类似「stacking context元素默认在非stacking context元素之上」定义的意义)

在W3C文档的某个角落,我们可以究其原委:

  

If an element with opacity less than 1 is not positioned, implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.

简言之,如果一个元素不是通过「定位」(position: absolute or relative)实现了stacking context,它将会以z-index: 0(高于auto)被看待,因此无论如何更改非「定位」元素的z-index都是无效的。

虽然文档中只提到opacity less 1构成的stacking context被看做z-index: 0,但通过测试,可以发现其他非「定位」方式创建的stacking context拥有与opacity less 1一致的表现。

以上便是我对CSS stacking context中造成诸多匪夷所思现象原因的总结。

*注:下文内容与题目无关,仅为作者思路延展

什么是GraphicLayer

浏览器在解析渲染document时,内部的处理并未直接暴露给我们,其中很重要的结构就是Layers。在这些未暴露的步骤中,RenderLayers负责渲染整个DOM子树结构,GraphicLayers则负责渲染RenderLayers中的子树,GraphicLayer把所负责的子树作为textures(可以理解为内存间移动的位图)upload到GPU,以实现高速绘制,也因而可以大幅优化这些属性带来的动画效果。

包括opacity在内,这些可产生stacking context的属性和创建特殊GraphicLayers的属性(opacity, filter, transfrom3d等)都很相似,但某些属性却又无法吻合(例如2d transfrom),冥冥之中总觉得两者原理上有相似之处,能力有限,只好留一坑。

Fixed定位脱离Viewport的bug

在定位中有一个跟stacking content无关但又较为相近的危险Bug,注意下面代码中.inner的定位:

See the Pen VLKeZP by abruzzi (@abruzzi) on CodePen.


http://codepen.io/abruzzi/pen/VLKeZP

对于声明transfrom值非none元素,其子元素中若存在position: fixed将以声明transform的最近祖先作为基准而定位,这是因为transfrom值非none的元素定义了一个局部坐标系统,导致postion: fixed以此坐标系统计算布局。
目前这个bug仍未被解决,官方建议避免在transform元素下做fixed定位。

by Abruzzi"s blog

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/111072.html

相关文章

  • 2018你成长了么?一份给你的前端技术清单

    摘要:由于个人精力有限,一些技术点的归纳可能有失偏颇,或者目前并未纳入进来,因此上的清单内容也会不断更新。 2018 眼看就要过去了,今年的你相较去年技术上有怎样的收获呢? 记得年初的时候我给自己制定了一个学习计划,现在回顾来看完成度还不错。但仍有些遗憾,一些技术点没有时间去好好学习。 在学习中我发现,像文章这样的知识往往是碎片化的,而前端涉及到的面很多,如果不将这些知识有效梳理,则无法形成...

    K_B_Z 评论0 收藏0
  • 2018你成长了么?一份给你的前端技术清单

    摘要:由于个人精力有限,一些技术点的归纳可能有失偏颇,或者目前并未纳入进来,因此上的清单内容也会不断更新。 2018 眼看就要过去了,今年的你相较去年技术上有怎样的收获呢? 记得年初的时候我给自己制定了一个学习计划,现在回顾来看完成度还不错。但仍有些遗憾,一些技术点没有时间去好好学习。 在学习中我发现,像文章这样的知识往往是碎片化的,而前端涉及到的面很多,如果不将这些知识有效梳理,则无法形成...

    LancerComet 评论0 收藏0
  • 2018你成长了么?一份给你的前端技术清单

    摘要:由于个人精力有限,一些技术点的归纳可能有失偏颇,或者目前并未纳入进来,因此上的清单内容也会不断更新。 2018 眼看就要过去了,今年的你相较去年技术上有怎样的收获呢? 记得年初的时候我给自己制定了一个学习计划,现在回顾来看完成度还不错。但仍有些遗憾,一些技术点没有时间去好好学习。 在学习中我发现,像文章这样的知识往往是碎片化的,而前端涉及到的面很多,如果不将这些知识有效梳理,则无法形成...

    Flands 评论0 收藏0
  • 深入 css z-index 屬性

    摘要:不能修改結構不能加入或修改任何元素的不能加入或修改任何屬性目標要完成下面這樣,先不要偷看解答自己想一想。當我們沒有和屬性的時候,規則非常簡單,就是按照文件中撰寫的先後順序。有設定且為,設定小於和其他等屬性也在此列。 說來汗顏,一直以來對於 css 常常是不求勝解。直到自己需要打造自己的輪子才發現對 z-index 完全不熟悉。關於 z-index 的問題其實非常少人完全明白它到底是怎麼...

    godlong_X 评论0 收藏0
  • CSS 中重要的层叠概念

    摘要:标签中的一切都被置于这个默认的层叠上下文的一个层叠层上物品放在桌子上。在层叠上下文中,其子元素按照上面解释的规则进行层叠。在中所有的盒模型元素都处于三维坐标系中。 最近在项目的过程中遇到了一个问题,menu-bar希望始终显示在最上面,而在之后的元素都显示在它之下,当时设置了 z-index 也没有效果,不知道什么原因,因此找了一下css有关层叠方面的资料,解决了这个问题,这里记录一下...

    sshe 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<