1. 前言

最近在项目开发过程中遇到了一个固定定位失效的问题,当给底部定位元素设置了position: fixed并设置了距离top和left,bottom的距离之后发现位置居然一直不正确,fixed固定定位失效了。

百度看了些文章说是父元素如果存在 transform 属性非none或者移动端设置-webkit-overflow-scrolling属性时会出现同样的问题

我的页面父元素未设置 transform ,就全局搜索了-webkit-overflow-scrolling,发现全局样式里设置了,百度了-webkit-overflow-scrolling导致fixed布局失效

2. 了解 -webkit-overflow-scrolling

-webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果,这样更自然,像是原生效果。

touch 使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。

所以我们一般会在需要滚动的元素上面加:-webkit-overflow-scrolling: touch; 这个 css 属性。
但是有当子元素有 fixed 定位时,fixed 定位会失效。

原因在于:
-webkit-overflow-scrolling 属性被设置 "touch"的元素 会创建一个堆叠上下文;
这时fixed 定位元素会由屏幕视口改为该祖先元素。所以会看到定位元素随着页面滚动而飞掉。

什么是堆叠上下文?

堆叠上下文(Stacking Context):堆叠上下文是 HTML 元素的三维概念,这些 HTML 元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的 z 轴上延伸,HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。

概念比较抽象,简单理解,就是 生成了 Stacking Context 的元素会影响 该元素的层叠关系与定位关系
总之,按照上面的说法,堆叠上下文的创建,该元素会影响其子元素的固定定位。设置了 position:fixed 的子元素将不会基于 viewport 定位,而是基于这个祖先元素。

解决方法:

因为 -webkit-overflow-scrolling导致fixed基于祖先元素定位,我页面内容没有铺满整个屏幕,导致fixed定位的元素上移,所以目前我的解决的方法是,设置最外层祖先元素 height:100vh;
如果有好的解决方法很欢迎一起交流哈~

3. 关于transform非none导致的无效

MND用一句话概括了这种情况:

当元素祖先的 transform 属性非 none 时,定位容器由视口改为该祖先。

所以如果fixed失效的情况下我们也可以查看祖先元素有transform的话要改为 transform:none

4. 总结:

以上两种导致fixed方法失效的原因都是创建了堆叠上下文,该元素会影响其子元素的固定定位。设置了 position:fixed 的子元素将不会基于 viewport 定位,而是基于这个父元素。

推荐:
https://www.jianshu.com/p/9125e7cf1fb0
https://blog.csdn.net/cjFrontEnd/article/details/90371376
解决 position: fixed 无效
不受控制的 position:fixed

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐