Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

position: sticky的polyfill #31

Open
coconilu opened this issue Aug 2, 2018 · 0 comments
Open

position: sticky的polyfill #31

coconilu opened this issue Aug 2, 2018 · 0 comments

Comments

@coconilu
Copy link
Owner

coconilu commented Aug 2, 2018

概述

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant