javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript元素吸顶

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

作者: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元素吸顶内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文