JavaScript实现元素吸顶的方法详解

 更新时间:2023年10月22日 09:21:26   作者:Qing  
页面内的tab导航需要在滚动到视口顶部的时候进行吸顶,这个功能算是比较常见,也比较容易实现,下面就跟随小编一起学习一下JavaScript是如何实现元素吸顶效果的吧

背景

页面内的tab导航需要在滚动到视口顶部的时候进行吸顶,这个功能算是比较常见,也比较容易实现。刚开始按照自己想到的最简单的方法来实现,写完代码后进行测试,发现页面有很明显的bug,心里直呼大意了,特此记录下。

错误示例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .page-container {
        width: 1200px;
        margin: 0 auto;
      }
      .top-area {
        height: 300px;
        background-color: lightskyblue;
        margin-bottom: 20px;
      }

      .tab {
        padding: 0 20px;
        display: flex;
        justify-content: space-between;
        background-color: #f4f4f4;
      }

      .tab.fixed {
        position: fixed;
        width: 1200px;
        box-sizing: border-box;
        top: 0;
      }

      .tab > div {
        padding: 10px 20px;
      }

      .waterfall {
        display: flex;
        justify-content: space-between;
        flex-wrap: wrap;
        align-content: center;
      }

      .waterfall > div {
        margin-top: 20px;
        width: 220px;
        height: 300px;
        background-color: darkseagreen;
        margin-bottom: 12px;
      }
    </style>
  </head>
  <body>
    <div class="page-container">
      <div class="top-area">huge element</div>
      <div class="tab">
        <div class="tab1">tab1</div>
        <div class="tab2">tab2</div>
        <div class="tab3">tab3</div>
        <div class="tab4">tab4</div>
        <div class="tab5">tab5</div>
        <div class="tab6">tab6</div>
        <div class="tab7">tab7</div>
        <div class="tab8">tab8</div>
        <div class="tab9">tab9</div>
        <div class="tab10">tab10</div>
      </div>
      <div class="tab-holder"></div>
      <div class="waterfall">
        <div class="item1">item1</div>
        <div class="item2">item2</div>
        <div class="item3">item3</div>
        <div class="item4">item4</div>
        <div class="item5">item5</div>
        <div class="item6">item6</div>
        <div class="item7">item7</div>
        <div class="item8">item8</div>
        <div class="item9">item9</div>
        <div class="item10">item10</div>
        <div class="item11">item11</div>
        <div class="item12">item12</div>
        <div class="item13">item13</div>
        <div class="item14">item14</div>
        <div class="item15">item15</div>
        <div class="item16">item16</div>
        <div class="item17">item17</div>
        <div class="item18">item18</div>
        <div class="item19">item19</div>
        <div class="item20">item20</div>
        <div class="item21">item21</div>
        <div class="item22">item22</div>
        <div class="item23">item23</div>
        <div class="item24">item24</div>
        <div class="item25">item25</div>
        <div class="item26">item26</div>
        <div class="item27">item27</div>
        <div class="item28">item28</div>
        <div class="item29">item29</div>
        <div class="item30">item30</div>
        <div class="item31">item31</div>
        <div class="item32">item32</div>
        <div class="item33">item33</div>
        <div class="item34">item34</div>
        <div class="item35">item35</div>
        <div class="item36">item36</div>
        <div class="item37">item37</div>
        <div class="item38">item38</div>
        <div class="item39">item39</div>
        <div class="item40">item40</div>
        <div class="item41">item41</div>
        <div class="item42">item42</div>
        <div class="item43">item43</div>
        <div class="item44">item44</div>
        <div class="item45">item45</div>
        <div class="item46">item46</div>
        <div class="item47">item47</div>
        <div class="item48">item48</div>
        <div class="item49">item49</div>
        <div class="item50">item50</div>
      </div>
    </div>
  </body>
  <script>
    const tabElem = document.querySelector(".tab");
    const tabHolder = document.querySelector(".tab-holder");

    const handleScroll = () => {
      const { top, height } = tabElem.getBoundingClientRect();
      console.log("top", top);
      if (top < 0) {
        tabElem.classList.add("fixed");
        tabHolder.style.height = height + "px";
      } else {
        tabElem.classList.remove("fixed");
        tabHolder.style.height = 0;
      }
    };

    document.addEventListener("scroll", handleScroll);
  </script>
</html>

上面的代码在打开页面后,向上滚动过程中会发现tab导航一直在闪烁,原因就是tab元素在转变成固定定位的过程,浏览器需要重新计算页面布局和重绘元素,在此期间滚动事件执行了很多遍,导致获取到的top值会出现两极跳转现象,元素会固定定位和原来的定位之间来回切换。

解决方案

上面的代码由于tab导航元素的定位会发生变化,导致在滚动过程中获取到的top值有问题,之前我们是使用需要定位的上边界来进行判断,那么我们可以选取相邻元素的上下边界是否达到条件来作为tab导航是否应该转为固定定位的依据。

const topAreaElem = document.querySelector(".top-area");
const tabElem = document.querySelector(".tab");
const tabHolder = document.querySelector(".tab-holder");

const handleScroll = () => {
  const { bottom } = topAreaElem.getBoundingClientRect();
  const { height } = tabElem.getBoundingClientRect();
  // 这个20是tab导航与上面相邻元素之间的margin
  if (bottom + 20 < 0) {
    tabElem.classList.add("fixed");
    tabHolder.style.height = height + "px";
  } else {
    tabElem.classList.remove("fixed");
    tabHolder.style.height = 0;
  }
};

document.addEventListener("scroll", handleScroll);

到此这篇关于JavaScript实现元素吸顶的方法详解的文章就介绍到这了,更多相关JavaScript元素吸顶内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript之解决IE下不渲染的bug

    javascript之解决IE下不渲染的bug

    javascript之解决IE下不渲染的bug...
    2007-06-06
  • JS实现评价的星星功能

    JS实现评价的星星功能

    这篇文章主要介绍了JS实现评价的星星功能,需要的朋友可以参考下
    2017-08-08
  • webpack中如何加载静态文件的方法步骤

    webpack中如何加载静态文件的方法步骤

    这篇文章主要介绍了webpack中如何加载静态文件的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • javascript中for...of和for..in循环的区别

    javascript中for...of和for..in循环的区别

    JS中循环语句众多,你是否也有用的时候突然不知道用哪个的经历,本文主要介绍了javascript中for...of和for..in循环的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • JavaScript中valueOf函数与toString方法深入理解

    JavaScript中valueOf函数与toString方法深入理解

    基本上,所有JS数据类型都拥有valueOf和toString这两个方法,null除外。它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下
    2012-12-12
  • 原生js实现九宫格拖拽换位

    原生js实现九宫格拖拽换位

    这篇文章主要为大家详细介绍了原生js实现九宫格拖拽换位,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • css静态滤镜 + A:Hover 效果

    css静态滤镜 + A:Hover 效果

    css静态滤镜 + A:Hover 效果...
    2007-05-05
  • 通过layer实现可输入的模态框的例子

    通过layer实现可输入的模态框的例子

    今天小编就为大家分享一篇通过layer实现可输入的模态框的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • IE6,IE7下js动态加载图片不显示错误

    IE6,IE7下js动态加载图片不显示错误

    ie6,7下js动态加载图片不显示错误,碰到这类问题的朋友可以参考下。
    2010-07-07
  • Js 本页面传值实现代码

    Js 本页面传值实现代码

    记得以前在学校的时候,例如要修改信息,需要要修改的部分的值显示出来,都是先把数据传到后台,然后再在前台显示的,想想真够笨的,这个可以在客户端就实现的,何必要传到后台呢
    2009-05-05

最新评论