实现一个简单的吸顶效果

541 阅读4分钟

最近遇到一个需求中有个实现吸顶效果,即页面滚动到顶部,某元素固定到底部,离开顶部后回到原位置。

第一反应就是position: sticky;毕竟之前使用过,感觉效果很好,本以为一个sticky就可以大功告成,可现实啪啪打脸呐,一查才知sticky使用有诸多条件。先来看看position:sticky 是什么

一. position:sticky

 基于用户的滚动位置来定位。粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换。

它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed; ,它会固定在目标位置。

元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。

这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。

正是由于超出目标区域才有固定效果,sticky元素效果完全受限于父级元素,使用条件:

1.sticky元素的父元素的overflow只能设置为visible,否则会导致没有粘滞效果

2.sticky元素的父元素不能设置固定的高度,否则会导致没有粘滞效果

3.sticky满足条件变成fixed定位时,与标准fixed元素不一样,不会脱离文档流

4.sticky 定位的元素不能添加一个只包含自身的父元素,会导致没有粘滞效果

5.同一个父级元素中的sticky元素,如果定位值相等,则会重叠,如果属于不同父级元素中,则会挤掉之前的元素

而且兼容性也不是很好,在ie下全部不适用,既然使用sticky限制条件较多,那就要找其他办法了最近遇到一个需求中有个实现吸顶效果,即页面滚动到顶部,某元素固定到底部,离开顶部后回到原位置。

第一反应就是position: sticky;毕竟之前使用过,感觉效果很好,本以为一个sticky就可以大功告成,可现实啪啪打脸呐,一查才知sticky使用有诸多条件。先来看看position:sticky 是什么\

一. position:sticky

 基于用户的滚动位置来定位。粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换。

它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed; ,它会固定在目标位置。

元素定位表现为在跨越特定阈值前为相对定位,之后为固定定位。

这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。

正是由于超出目标区域才有固定效果,sticky元素效果完全受限于父级元素,使用条件:

1.sticky元素的父元素的overflow只能设置为visible,否则会导致没有粘滞效果

2.sticky元素的父元素不能设置固定的高度,否则会导致没有粘滞效果

3.sticky满足条件变成fixed定位时,与标准fixed元素不一样,不会脱离文档流

4.sticky 定位的元素不能添加一个只包含自身的父元素,会导致没有粘滞效果

5.同一个父级元素中的sticky元素,如果定位值相等,则会重叠,如果属于不同父级元素中,则会挤掉之前的元素

而且兼容性也不是很好,在ie下全部不适用,既然使用sticky限制条件较多,那就要找其他办法了

image.png

二.使用offsetTop

HTMLElement.offsetTop 为只读属性,它返回当前元素相对于其 offsetParent 元素的顶部内边距的距离。因此我们需要注意的是,在监听页面滚动的过程中,需要将定位父级元素的偏移量也计算在内,可以如下写法:

    //获取当前元素的offsetTop
    getOffsetTop(obj) {
      let offsetTop = 0;
      while (obj != window.document.body && obj != null) {
        offsetTop += obj.offsetTop;
        obj = obj.offsetParent;
      }
      return offsetTop;
    }

通过添加监听事件滚动的事件:

       window.addEventListener("scroll", handleScroll);
       /**滚动事件 */
        function handleScroll() {
            //获取页面滚动条的高度
            let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
            let offsetTop = getOffsetTop(element);
            return scrollTop > offsetTop;
        }

三、使用getBoundingClientRect().top

还有一种更为直接的方式,可以实现吸顶效果,就是使用getBoundingClientRect().top来获取元素相对于视口(浏览器窗口)的位置,相对于offsetTop,该方法不用考虑到吸顶元素的父级元素和页面滚动条的高度,直接对该元素进行处理即可

     /**滚动事件 */
    function handleScroll() {
      /**
       * getBoundingClientRect().top 获取某元素距离浏览器顶部的高度,不包含滚动的距离
       offsetTop 表示的是吸顶元素距离顶部的条件值(一般项目需求是0)
       */
      let tabOffsetTop = document.getElementById('element').stickyBox.getBoundingClientRect().top;
      return tabOffsetTop < offsetTop
    }

以上就是实现需求得三个方式,也许还有更好得方法,待大家指教。