transform是个超级常用的属性, 需要居中/动画/开启cpu加速时经常会用到.
但这个属性也有很多副作用, 例如把后边的元素盖住了,或者是后代absolute元素被overflow:hidden剪裁.
除此之外还有个影响, 让拥有固定定位(fixed)属性的子元素变的像个绝对定位(absolute)元素.
如上图所示, 黑色子元素为固定定位元素(fixed), 由于黄色父元素transfrom属性的影响, 表现的像个绝对定位元素(absolute).
示例代码:
1 | <div class="wrapper"> |
1 | .wrapper { |
原因
根据css规范:
1 | In the HTML namespace, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants. |
也就是说,如果fixed元素的祖先有transform属性,则fixed元素会相对与这个祖先计算,而不是视口.
什么是"containing block"?
通常情况下(position: static/relative),包含块指的是距离元素最近的"祖先元素的内容区",也就是父元素.
如果position属性值为absolute, 则将"距离该元素最近"且"position属性值不为none"的祖先元素作为包含块.
如果position属性值为fixed, 则将"视口"(viewport)作为包含块.
除此之外, 如果祖先元素拥有下列属性,也可能被作为absolute和fixed的包含块.
- transform/perspective属性值不为none
- will-change属性值为transform/perspective
解决办法
不要把固定定位元素放在拥有transform/will-change属性值的元素里面.
导航栏之类的元素也可以用sticky代替fixed,不过sticky的兼容性不太好.
另外,很多动画库都会使用transform来优化动画效果, 如果fixed元素出了什么奇怪的bug,那很可能是这些库搞得鬼.
参考
CSS3 transform对普通元素的N多渲染影响 « 张鑫旭-鑫空间-鑫生活
css - 'transform3d' not working with position: fixed children - Stack Overflow