Skip to content

position: sticky的polyfill #31

@coconilu

Description

@coconilu

概述

position: sticky是新增的css属性,粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。

polyfill

其实这样的效果可以使用JS来实现,下面的链接就是我写的polyfill

position: sticky 的兼容代码

/**
* position: sticky的polyfill
* 推荐在文档加载完成之后(‘DOMContentLoaded’事件)调用
* @param {String} selectors 选择器
* @param {String} top 距离顶部的偏移量
*/
function sticky(selectors, top = 0) {
  let elements = document.querySelectorAll(selectors);
  for (let i = 0; i < elements.length; ++i) {
    elements[i].dataset['originOffsetTop'] = elements[i].getBoundingClientRect().top + ((window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop)
  }
  window.addEventListener('scroll', onScroll(elements, top));

  function onScroll(elements, top) {
    let shouldRun = true
    return () => {
      let scrollY = window.pageYOffset;
      if (shouldRun) {
        // 节流代码
        shouldRun = false
        for (let i = 0; i < elements.length; ++i) {
          let element = elements[i];
          console.log(element)
          // 判断是relative条件还是fixed条件
          if (element.dataset['originOffsetTop'] - scrollY <= top && !element.$isSticky) {
            // fixed条件
            fixed(element, top)
          }
          if (element.dataset['originOffsetTop'] - scrollY > top && element.$isSticky) {
            // relative条件
            element.$unFixed && element.$unFixed()
          }
        }
        setTimeout(() => {
          shouldRun = true
        }, 100)
      }
    }
  }

  function fixed(element, top) {
    let originCss = element.style.cssText;
    element.style.cssText += ";position: fixed; top: " + top + "px;";
    element.$isSticky = true
    element.$unFixed = () => {
      element.$isSticky = false
      element.style.cssText = originCss;
    }
  }
}

思路

  1. 获取元素初始化时候的offsetTop,并存储在元素的dataset中
  2. 监听滚动条事件,并使用节流方式处理滚动事件处理器
  3. 在事件处理器里,获取浏览器的纵轴的滚动偏移量——window.pageYOffset,然后跟元素的纵轴偏移量作比较,判断是否需要对元素做position: fixed处理,或者还原positon

因为需要把元素设置为 position: fixed;所以元素的width和height需要制定确切的值

API

该库仅对外提供一个接口:

/**
* position: sticky的polyfill
* 推荐在文档加载完成之后(‘DOMContentLoaded’事件)调用
* @param {String} selectors 选择器
* @param {String} top 距离顶部的偏移量
*/
function sticky(selectors, top = 0)

NPM地址

案例

可以在CodePen上看到效果。

参考

position

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions