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

解決方案
上面的代碼由于tab導(dǎo)航元素的定位會(huì)發(fā)生變化,導(dǎo)致在滾動(dòng)過程中獲取到的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();
// 這個(gè)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實(shí)現(xiàn)元素吸頂?shù)姆椒ㄔ斀獾奈恼戮徒榻B到這了,更多相關(guān)JavaScript元素吸頂內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
javascript或asp實(shí)現(xiàn)的判斷身份證號(hào)碼是否正確兩種驗(yàn)證方法
在網(wǎng)頁中經(jīng)常需要輸入正確的身份證號(hào)碼,只能通過程序來驗(yàn)證身份證格式。根據(jù)身份證號(hào)碼生成的原理,就是驗(yàn)證后面幾位就可以了。
2009-11-11
-
購物車前端開發(fā)(jQuery和bootstrap3)
針對(duì)購物車的操作,進(jìn)行產(chǎn)品數(shù)量的增加減少,刪除購物車中產(chǎn)品項(xiàng),本文使用JQuery1.11和bootstrap3進(jìn)行購物車開發(fā),感興趣的小伙伴們 2016-08-08
-
JavaScript 獲取用戶客戶端操作系統(tǒng)版本
今天,同事反映部分電腦訪問系統(tǒng),安裝播放器(Media Player)報(bào)錯(cuò),自己本機(jī)測(cè)試沒問題,但是去用戶現(xiàn)場(chǎng)查看情況,部分電腦確實(shí)存在此類問題,不知道問題出在何處,希望我?guī)椭鉀Q一下。
2009-08-08
-
微信小程序中時(shí)間戳和日期的相互轉(zhuǎn)換問題
這篇文章主要介紹了微信小程序中時(shí)間戳和日期的相互轉(zhuǎn)換問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下 2018-07-07
-
在TypeScript中迭代對(duì)象鍵Object.keys不起作用的原因和解決方案
在TypeScript中迭代對(duì)象鍵object?keys可能是一場(chǎng)噩夢(mèng),以下是我所知道的所有解決方案,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下 2023-10-10
-
JS構(gòu)造函數(shù)與原型prototype的區(qū)別介紹
下面小編就為大家?guī)硪黄狫S構(gòu)造函數(shù)與原型prototype的區(qū)別介紹。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧 2016-07-07
最新評(píng)論
背景
頁面內(nèi)的tab導(dǎo)航需要在滾動(dòng)到視口頂部的時(shí)候進(jìn)行吸頂,這個(gè)功能算是比較常見,也比較容易實(shí)現(xiàn)。剛開始按照自己想到的最簡(jiǎn)單的方法來實(shí)現(xiàn),寫完代碼后進(jìn)行測(cè)試,發(fā)現(xiàn)頁面有很明顯的bug,心里直呼大意了,特此記錄下。
錯(cuò)誤示例
<!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>上面的代碼在打開頁面后,向上滾動(dòng)過程中會(huì)發(fā)現(xiàn)tab導(dǎo)航一直在閃爍,原因就是tab元素在轉(zhuǎn)變成固定定位的過程,瀏覽器需要重新計(jì)算頁面布局和重繪元素,在此期間滾動(dòng)事件執(zhí)行了很多遍,導(dǎo)致獲取到的top值會(huì)出現(xiàn)兩極跳轉(zhuǎn)現(xiàn)象,元素會(huì)固定定位和原來的定位之間來回切換。

解決方案
上面的代碼由于tab導(dǎo)航元素的定位會(huì)發(fā)生變化,導(dǎo)致在滾動(dòng)過程中獲取到的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();
// 這個(gè)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實(shí)現(xiàn)元素吸頂?shù)姆椒ㄔ斀獾奈恼戮徒榻B到這了,更多相關(guān)JavaScript元素吸頂內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript或asp實(shí)現(xiàn)的判斷身份證號(hào)碼是否正確兩種驗(yàn)證方法
在網(wǎng)頁中經(jīng)常需要輸入正確的身份證號(hào)碼,只能通過程序來驗(yàn)證身份證格式。根據(jù)身份證號(hào)碼生成的原理,就是驗(yàn)證后面幾位就可以了。2009-11-11
購物車前端開發(fā)(jQuery和bootstrap3)
針對(duì)購物車的操作,進(jìn)行產(chǎn)品數(shù)量的增加減少,刪除購物車中產(chǎn)品項(xiàng),本文使用JQuery1.11和bootstrap3進(jìn)行購物車開發(fā),感興趣的小伙伴們2016-08-08
JavaScript 獲取用戶客戶端操作系統(tǒng)版本
今天,同事反映部分電腦訪問系統(tǒng),安裝播放器(Media Player)報(bào)錯(cuò),自己本機(jī)測(cè)試沒問題,但是去用戶現(xiàn)場(chǎng)查看情況,部分電腦確實(shí)存在此類問題,不知道問題出在何處,希望我?guī)椭鉀Q一下。2009-08-08
微信小程序中時(shí)間戳和日期的相互轉(zhuǎn)換問題
這篇文章主要介紹了微信小程序中時(shí)間戳和日期的相互轉(zhuǎn)換問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
在TypeScript中迭代對(duì)象鍵Object.keys不起作用的原因和解決方案
在TypeScript中迭代對(duì)象鍵object?keys可能是一場(chǎng)噩夢(mèng),以下是我所知道的所有解決方案,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10
JS構(gòu)造函數(shù)與原型prototype的區(qū)別介紹
下面小編就為大家?guī)硪黄狫S構(gòu)造函數(shù)與原型prototype的區(qū)別介紹。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07

