導航欄載入時可能出現閃的原因以及解決辦法
阿新 • • 發佈:2019-01-26
元素閃爍很醜,難解決。
修改 Class 而不是 Style
我在不久前做過一個導航欄,要求其滾動到螢幕頂端後固定。很常見。開始的時候沒問題,很快就可以搞定。
nav {
position: absolute;
top: 60px;
}
var scroll=0;
var nav=$("nav");
var navST=60; //該元素距離網頁頂端60px
$(window).scroll(function(){
if($(document).scrollTop()>navST && scroll==0){
nav.css({position : "fixed",top: "0"});
scroll=1;
}
else if($(document).scrollTop()<=navST && scroll==1){
nav.removeAttr("style");
scroll=0;
}
});
執行很流暢。
做好,我自然就忙著網頁內容去了。沒曾想,隨著頁面 JS 的不斷增加,導航欄在固定時出現了可怕的閃動。
唔,就是 一下看得見 一下看不見 的東西!
應該有不少人和我一樣。百度,無果。谷歌,看不懂,翻譯也不行。
不知道真相的我,眼淚 流下來。
哦!一道莫名的亮光從我的眼前閃過!這道亮光裡,有希望,,有興奮,,組成了四個大字:
元素重繪
就在這千萬分之一秒,億萬分之一秒 裡,我理解了:
nav.css({position: "fixed",top: "0"});
這一句 JS 產生了兩次 DOM 寫入,影響瀏覽器渲染頁面兩次。
使用 $.addClass 語句可以解決。
nav {
position: absolute;
top: 60px;
}
.fixed {
position: fixed;
top: 0;
}
var scroll=0;
var nav=$("nav");
var navST=60; //該元素距離網頁頂端60px
$(window).scroll(function(){
if($(document).scrollTop()>navST && scroll==0){
nav.addClass("fixed");
scroll=1;
}
else if($(document).scrollTop()<=navST && scroll==1){
nav.removeClass("fixed");
scroll=0;
}
});
閃爍問題得到了臨時解決。
採用不可見元素減少 DOM 變更產生的運算
“臨時” 說法的原因是當 JS 數量再次增加,達到又一新高度後,閃爍問題再現。
原因大概是 $.addClass 時瀏覽器需要重新計算該元素位置, JS 數量過多使計算過程明顯。
不多說,在 HTML 裡多放一個包含 .fixed 的寬高為 0 的元素即可解決。
<div class="fixed"></div>
<nav>something...</nav>
別讓這個 div.fixed 顯示出來。
至此,全面解決 “動態新增樣式導致的元素閃爍” 。
原生 JS 進一步加快速度避免閃爍
jQuery 是個好東西。原生 JS 更是個好東西。
有些 jQuery 程式碼,被轉化為好多條原生 JS 才實現效果。
然而其實只需要一條。
將 jQuery 程式碼轉化為原生 JS 是個加快速度,避免閃爍的不二選擇。
var scroll=0;
var navST=60; //該元素距離網頁頂端60px
window.onscroll = function(){
if(document.documentElement.scrollTop || document.body.scrollTop>navST && scroll==0){
document.getElementsByTagName("nav")[0].classList.add("fixed");
scroll=1;
}
else if(document.documentElement.scrollTop || document.body.scrollTop<=navST && scroll==1){
document.getElementsByTagName("nav")[0].classList.remove("fixed");
scroll=0;
}
};