JavaScript實現(xiàn)元素吸頂?shù)姆椒ㄔ斀?/h1>
更新時間:2023年10月22日 09:21:26 作者:Qing
頁面內(nèi)的tab導(dǎo)航需要在滾動到視口頂部的時候進(jìn)行吸頂,這個功能算是比較常見,也比較容易實現(xiàn),下面就跟隨小編一起學(xué)習(xí)一下JavaScript是如何實現(xiàn)元素吸頂效果的吧
背景
頁面內(nèi)的tab導(dǎo)航需要在滾動到視口頂部的時候進(jìn)行吸頂,這個功能算是比較常見,也比較容易實現(xiàn)。剛開始按照自己想到的最簡單的方法來實現(xiàn),寫完代碼后進(jìn)行測試,發(fā)現(xiàn)頁面有很明顯的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>
上面的代碼在打開頁面后,向上滾動過程中會發(fā)現(xiàn)tab導(dǎo)航一直在閃爍,原因就是tab元素在轉(zhuǎn)變成固定定位的過程,瀏覽器需要重新計算頁面布局和重繪元素,在此期間滾動事件執(zhí)行了很多遍,導(dǎo)致獲取到的top值會出現(xiàn)兩極跳轉(zhuǎn)現(xiàn)象,元素會固定定位和原來的定位之間來回切換。

解決方案
上面的代碼由于tab導(dǎo)航元素的定位會發(fā)生變化,導(dǎo)致在滾動過程中獲取到的top值有問題,之前我們是使用需要定位的上邊界來進(jìn)行判斷,那么我們可以選取相鄰元素的上下邊界是否達(dá)到條件來作為tab導(dǎo)航是否應(yīng)該轉(zhuǎn)為固定定位的依據(jù)。
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導(dǎo)航與上面相鄰元素之間的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);
到此這篇關(guān)于JavaScript實現(xiàn)元素吸頂?shù)姆椒ㄔ斀獾奈恼戮徒榻B到這了,更多相關(guān)JavaScript元素吸頂內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
JavaScript獲取上傳進(jìn)度的幾種方式實現(xiàn)
進(jìn)度條的應(yīng)用是為了顯示的告訴用戶文件上傳了多少,本文主要介紹了JavaScript獲取上傳進(jìn)度的幾種方式,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧 2023-08-08
-
淺談javascript的url參數(shù)parse和build函數(shù)
下面小編就為大家?guī)硪黄獪\談javascript的url參數(shù)parse和build函數(shù)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧 2017-03-03
-
confirm的用法示例用于按鈕操作時確定是否執(zhí)行
這篇文章主要介紹了confirm的用法,confirm一般用于按鈕操作時確定是否執(zhí)行,需要的朋友可以參考下 2014-06-06
最新評論
背景
頁面內(nèi)的tab導(dǎo)航需要在滾動到視口頂部的時候進(jìn)行吸頂,這個功能算是比較常見,也比較容易實現(xiàn)。剛開始按照自己想到的最簡單的方法來實現(xiàn),寫完代碼后進(jìn)行測試,發(fā)現(xiàn)頁面有很明顯的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>
上面的代碼在打開頁面后,向上滾動過程中會發(fā)現(xiàn)tab導(dǎo)航一直在閃爍,原因就是tab元素在轉(zhuǎn)變成固定定位的過程,瀏覽器需要重新計算頁面布局和重繪元素,在此期間滾動事件執(zhí)行了很多遍,導(dǎo)致獲取到的top值會出現(xiàn)兩極跳轉(zhuǎn)現(xiàn)象,元素會固定定位和原來的定位之間來回切換。
解決方案
上面的代碼由于tab導(dǎo)航元素的定位會發(fā)生變化,導(dǎo)致在滾動過程中獲取到的top值有問題,之前我們是使用需要定位的上邊界來進(jìn)行判斷,那么我們可以選取相鄰元素的上下邊界是否達(dá)到條件來作為tab導(dǎo)航是否應(yīng)該轉(zhuǎn)為固定定位的依據(jù)。
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導(dǎo)航與上面相鄰元素之間的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);
到此這篇關(guān)于JavaScript實現(xiàn)元素吸頂?shù)姆椒ㄔ斀獾奈恼戮徒榻B到這了,更多相關(guān)JavaScript元素吸頂內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript獲取上傳進(jìn)度的幾種方式實現(xiàn)
進(jìn)度條的應(yīng)用是為了顯示的告訴用戶文件上傳了多少,本文主要介紹了JavaScript獲取上傳進(jìn)度的幾種方式,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08淺談javascript的url參數(shù)parse和build函數(shù)
下面小編就為大家?guī)硪黄獪\談javascript的url參數(shù)parse和build函數(shù)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03confirm的用法示例用于按鈕操作時確定是否執(zhí)行
這篇文章主要介紹了confirm的用法,confirm一般用于按鈕操作時確定是否執(zhí)行,需要的朋友可以參考下2014-06-06