最近临摹华为官网的时候再一处导航栏遇到了意外的情况,导航栏分为 A、B、C 三部分,分别位于同一行的左、中、右,如下图:
为了将这3个元素并列在一行上,设置了 A、C 均为 Float,B 为 Absolute, 且 A、B、C 均可以被点击。但是写完 HTML 和 CSS 后却发现除了 B 之外,都无法点击。
排查后发现是 A、C 被 B 遮挡的原因,于是尝试通过 z-index 的来解决。
为此搭建了一个简单模型来尝试解决,代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>test</title> <style> .container { position: relative; width: 100%; background-color: #000; margin-top: 100px; padding: 20px; box-sizing: border-box; } .container::before, .container::after { display: block; content: ""; clear: both; } .fl { float: left; width: 40px; height: 80px; background-color: #0051ff; z-index: 0; } .ab { position: absolute; bottom: 0; left: 0; width: 98%; height: 60px; background-color: #ffc400; z-index: 0; } .fr { float: right; width: 40px; height: 80px; background-color: #ff0000; z-index: 0; } </style></head><body> <div class="container"> <div class="fl">float left</div> <div class="fr">float right</div> <div class="ab"> absolute</div> </div></body></html>
(这是在线代码:codepen.io/sangyaaak/p…
结果如下图:
果然 abosolute 元素挡住了 float 元素,推测是因为 float 元素属于半脱离文档流,而 abosolute 元素完全脱离文档流,因此 absolute 元素总是在当前的文档流之上,当然也就覆盖住了 float。
有什么办法可以解决?
方法是为 absolute 元素设置一个 z-index: -1,将 absolute 元素的堆叠高度降到文档流底下,这样就能不会挡住 float 元素了。结果如下:
黄色 absolute 块怎么不见呢?原因是它掉到了 黑色的 container 底下了,将 container 的背景色调透明就能看到。
这不是我想要的,我希望 abosolute 不挡住 float,并且在 container 之上,该怎么办?
答案是为 container 设定一个 z-index: 0;
看,黄色的 absolute 块回到了 float 块的底下,同时又不会掉到出 container 底下。
不要尝试对 float 元素设置 z-index, 因为 z-index 对 float 无效;准确的说应该是元素默认为 position: static;只设置 float 时并没有改变他的 position,而 z-index 仅对 static 元素无效。
Note:
z-indexonly works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky).
所以除非你给他设置其他的 position, 否则就无法用 z-index控制其堆叠的顺序。
后面还对 z-index 做了很多的实验,发现不少奇怪现象(可能是 bug),在次不再赘述过程,仅把所有的结论列出来。
1、z-index 只对拥有 position 属性的元素生效, position = static 除外。
2、z-index 表示的是元素与其在同一 “容器” 内的其他元素的堆叠顺序(order),有效值为整数。
3、未声明 z-index 和 static 元素的 z-index 默认为 0,堆叠顺序按渲染时序由前到后排,先渲染则在下,依次向上堆叠。
4、正常情况下,子元素(child)总是在其父元素(parent)之内,不管子元素(child)的 z-index 多大/多小,子元素都不会在比其父元素低的元素之下或之上。
// 举个栗子:
//以下有两组标签,父元素<A>、<B>分别有子元素,且 z-index 各不相同。
<body> <A> // A z-index = -1
<AA_1> // AA_1 z-index = 10 <AA_2> // AA_2 z-index = 20
</A>
<B> // B z-index = 1 <BB_1> // BB_1 z-index = -100
</B>
</body>
堆叠顺序结果如下:
虽然<BB_1>的 z-index 为 -100, 但只是对于内的元素而言,并不与之外的元素比较顺序。
但是!!!以上的情况仅发生在所有元素都设定了有效的 z-index 值。否则会出现以下情况:
(以下为类似bug的发现)
1、子元素设有 z-index 而父元素没有设定时,子元素会不断向外寻找,直到发现某个外层元素设有 z-index 并将其作为容器,若未发现则以 为容器。
2、父元素设定 z-index 的子元素则表现正常。
3、除了设定 z-index 外,设定 opacity ,但值必须 <1,这样也可以解决以上奇怪现象。
// 举个栗子:
//以下有两组标签,父元素<A>、<B>分别有子元素,且 z-index 各不相同。
<body>
<A> //
<AA_1> // AA_1 z-index = 10
<AA_2> // AA_2 z-index = 20
</A>
<B> //
<BB_1> // BB_1 z-index = -100
</B>
</body>
堆叠顺序结果如下:
// 再举个栗子:
//以下有两组标签,父元素<A>、<B>分别有子元素,且 z-index 各不相同。
<body>
<A> //
<AA_1> // AA_1 z-index = 10
<AA_2> // AA_2 z-index = 20
</A>
<B> // B z-index = 15
<BB_1> // BB_1 z-index = -100
</B>
</body>
堆叠顺序结果如下:
以上
如果发现元素之间的遮挡关系很奇怪的话,还是好好检查下父元素和子元素之间的 z-index 吧。