# 【小技巧】-滚动置顶还能这么玩

# 需求描述

前段时间接到一个小的需求,一个tab在滚动到顶部的时候置顶,然后当页面向上滑动到一定位置的时候置顶效果消失,我们来看一下示意图: An image

# 通过js来实现(旧方案)

好吧,拿到需求就开始一顿敲,最开始的版本通过纯js的方式实现了这个效果,demo代码如下:




 














































<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
* {
    margin: 0;
    padding: 0;
}
.box {
    height: 50px;
    background-color: red;
}
.top-box {
    height: 400px;
}
.bottom-box {
    height: 1000px;
}
</style>
<body>
    <div class="app">
        <div class="top-box"></div>
        <div id="box" class="box"></div>
        <div class="bottom-box"></div>
    </div>
    <script>
        let box = document.getElementById('box')
        let offsetTop = box.offsetTop
        window.onscroll = () => {
            // 页面滚动的距离
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
            console.log(scrollTop, offsetTop)
            if (scrollTop >= offsetTop) {
             box.style.position = 'fixed'
             box.style.left = 0
             box.style.right = 0
             box.style.top = 0
            } else {
             box.style.position = 'relative'
            }
        }
    </script>
</body>
</html>

其实代码很简单,通过当前滚动的高度和元素渲染时候距离顶部的高度进行比较,改变元素的position属性就可以实现这个效果。但是在code-review的时候,组内其他成员的评论中涉及到了一种新的好玩的方法,2行代码就可以实现这个效果,作为一个“负责的程序员”,研究了一手.

# position: sticky

其实我们想实现这个效果,只需要在对应的元素上添加以下两行css就可以了




    position: sticky;
    top: 0;

position : sticky是css定位新增属性;可以说是相对定位relative和固定定位fixed的结合;它主要用在对scroll事件的监听上;简单来说,在滑动过程中,某个元素距离其父元素的距离达到sticky粘性定位的要求时(比如top:100px);position:sticky这时的效果相当于fixed定位,固定到适当位置。

# position: sticky 的不足

但是这个属性也不是想象中的这么好用,还是有一定的限制条件的,如:

  • 父元素不能overflow:hidden或者overflow:auto属性。
  • 必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
  • 父元素的高度不能低于sticky元素的高度
  • sticky元素仅在其父元素内生效

而且,对于处于移动端开发小组的我来说,使用这个属性最重要的一点就是这个属性的兼容性了,我们看一下这个的兼容性

An image

emmmmmmm好像兼容性不是很好,而且看了网上一些同学说这个属性对安卓系统的兼容有点惨,作为一个合格的程序员,默默的选择后者,兼容bug来了再说嘛。

# 总结

对于需要考虑多种兼容性的情况下,还是老老实实的通过js来实现,如果再兼容条件允许的情况下,后者是很好的一个选择。