position:sticky 踩坑记录
背景
最近在移动端需要实现导航栏的粘性布局,看到原型的时候也就想了下怎么实现。不外乎是通过js监听window的scroll事件,当需要固定的元素滚动到窗口顶部时,把元素的position属性设置为fixed,否则,取消fixed,简单代码如下:
|
开发的时候一直在用Chrome的模拟器,滑动起来很顺畅,后来测试的时候用真机发现粘顶效果很不好。ios滑动的时候会暂停所有的js执行,等待滚动完成之后才会执行,所以上面代码的监听并没有在滑动时响应。安卓机下面相对好一点。但是作为一个水果机,竟然有如此不优雅的展现方式,怎么对得起乔帮主的在天之灵啊!
既然浏览器自带滚动条不适用,就尝试用类似iscroll插件模拟滚动条,但是考量了一下,滚动页面需要上拉加载更多,需要对整页进行iscroll,损耗性能不说还要重新实现iscroll(或者引入插件)。所以准备使用position的新属性 Sticky。
##Sticky positioning
sticky布局是一个类似relative和fixed的混合布局。在视窗范围内,元素会以relative布局显示,当超过阀值时会以fixed布局显示。参照
例如:
当页面滚动到sticky在文档流中位置元素离视窗顶端的距离<=10px时,sticky元素就开始固定了,当sticky元素在文档流中位置离viewport顶端的距离>10px时,元素就不再固定。
至此,sticky属性完全符合我们的要求。但是很遗憾,作为一个实验属性,有很多浏览器并没有实现该属性。大家看看下图:
chrome下全红,安卓下也基本没有实现。庆幸的是,我现在只需要照顾到移动端方面,ios6+都已经支持了该属性,安卓下就使用fixed属性好了。
##生效条件
按照上面的方法设置好,很大程度上还是不会实现粘顶的效果,查了很多资料,都没有给出很好的原因,然后我就硬着头皮去看官方文档。发现sticky属性是有生效条件的。
- 任何一级父节点都不能overflow为非visible,否则都不会生效
- 设置了postion:sticky的元素要生效必须要至少设置top,bottom,left,right中的一个属性,并且同时设置时,top>bottom,left>right。
参考:
CSS Positioned Layout Module Level 3
CSS “position: sticky” – Introduction and Polyfills