ICE和层叠问题其实都是老问题了,本文只是挪一下之前的share。
什么是ICE?
ICE其实就是id、class、element的缩写,它们分别表征了不同的样式优先级,如果以权值来衡量,那么它们分别对应的权将是I:100,C:10,E:1,伪类,eg. :link 属C,伪元素,eg. :first-child 属E。除此之外继承-extends的权为0.1,!important的权最高(我们在样式表中看到该设置,往往意味着开发者不想该样式将来被别的内联或者其他附加的样式属性所覆盖或重写)。
我们通过计算ICE权值,样式以最高者优先。
优先级比较
父与子(继承)
前面我们也提到了继承的权值,什么是样式继承的场景?比如2个容器盒子,外部盒子有一个样式类,那么内部包裹的盒子即便没有设置样式,也会继承父级的样式设置。
后来者居上(层叠)
多个样式类,后面类的相同属性设置会覆盖前面类的设置,不同则会合并(所以样式表构造的时候,相同部分能够抽离,不同的特异的可以单独做一个)。
你大爷还是你大爷(!important)
!important > 内联样式 > id > class | 伪类 | 属性选择器[type=button]
> 元素 > 通配符 > 继承
所以你要是发现你的样式怎么改都没用,那基本是代码里有大哥了,全局搜一下。
怎么算?
大家都是聪明人,举个栗子就够了:div#0 span
,元素有div和span,一个id选择器,权就是1x2+100=102。
布局层叠顺序
这里的层叠跟前文中的CSS权值比较重的层叠不是一个东西,专指布局中的层叠顺序。故事的起源比较久远了,想当年…在做一个水印需求的时候由于对这方面的知识不够熟悉,踩了很多坑。
那次踩坑给我最大的感悟是,兼容性很重要,任何你添加的样式属性要三思而后行,建议先去canIuse上看一下各个浏览器及其各个版本的支持情况。
说说我当时实现的思路:首先获取包裹的外层,再在该包裹容器下appendChild,将生成的水印层添加到末尾,为水印层设置position:absolute,给一个较高的z-index值,设置透明度属性opacity,然后就是关键先生pointer-events: none了,这个属性的本意是使元素永远不会成为鼠标事件的target,即不会影响到下面的点击表单事件。CHROME表现正常,但IE到11才支持该属性,所以直接导致要换方法实现。
后续改写的时候我卡在了一个地方:我当时一直认为设置了absolute脱离文档流后,在点击或者说层级上应该是在上面的会挡住下面的表单。
然而看了张鑫旭老湿的文章后我发现有这么一个东西:
WTF!?定位元素(relative,absolute)在默认情况下的z-index为auto,并且遵循后来追上原则,即DOM流后面的会覆盖前面的,对应我们水印场景中的relative表单会覆盖前面的absolute水印层,而不是之前想当然的那种absolute就一定浮动在上面。
所以,其实只需要在主体的DOM前insertBefore
需要的水印,然后包裹层设置溢出隐藏overflow: hidden
即可。
DOM布局如下: