回到頁面頂部、兼容性、最佳寫法、滾動到任意處javascript
在 你們一塊兒被捕吧 中剛寫了:css
在平常開發中咱們每每會從用戶那得到各類輸入,例如搜索框、評論框、文章內容等等。html
結果在 segmentfault
閱讀評論時看到了一個連接一點直接把我給滾動到頂部
,頓時心中一陣 慘叫雙手捶胸
後把頁面拉回評論並打開了 控制檯
查看了連接爲什麼方神聖:java
<a href="#">...</a>
複製代碼
頓時又是一陣 慘叫雙手捶胸
原來 segmentfault
評論是支持 markdown 語法的,若是再評論裏輸入 [...](#)
則會被轉換成如上代碼。git
好奇心突發跑到了 掘金
測試了一下帶鏈接的評論,打開 控制檯
看了看因爲使用了 target="_blank"
沒有出現被傳送到頂部的狀況,內心暗暗道 喵哉 🐱
之後仍是得當心行事,碰巧每日30秒正愁不知道寫什麼那就來寫寫 回到頂部
吧。github
第一種寫法就介紹一下今天被中全套的代碼,利用了 錨點
來實現回到頂部:segmentfault
<a href="#"回頂部></a>
複製代碼
若是須要滾動到別的元素可使用 id
屬性配合 錨點
來實現:瀏覽器
<header id="header">我是頭部</header>
<a href="#header">回到頁面頭部</a>
複製代碼
不過因爲這種方法 滾動
得太快了,性能確定是很好就是體驗不怎麼好。不過咱們可使用 css 的 scroll-behavior
屬性來提高體驗:微信
html, body {
scroll-behavior: smooth;
}
複製代碼
雖然第一種方法配合 css 的 scroll-behavior
屬性顯得挺不錯,可是 scroll-behavior
兼容性挺不高的具體能夠看 caniuse。markdown
因爲在頁面垂直滾動過程當中會改變 window.scrollY
的值,第二種即是寫法利用 window.scrollTo()
把它設置爲 0
來實現回到頂部:
window.scrollTo(0, 0)
複製代碼
不過這樣使用也會致使 滾動
得太快帶來的體驗很差,這個時候咱們能夠利用 window.requestAnimationFrame()
告訴瀏覽器——你但願執行一個動畫,而且要求瀏覽器在下次重繪以前調用指定的回調函數更新動畫,該方法須要傳入一個回調函數做爲參數,該回調函數會在瀏覽器下一次重繪以前執行。
這裏使用裏一個來判斷當頁面沒有滾動到頂部時循環調用 window.requestAnimationFrame
來進行逐步滾動,每次滾動的距離 c - c / 8
隨着 c
的減少而減少進而實現滾動效果:
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
複製代碼
不過繼續查閱 caniuse 中的 window.requestAnimationFrame()
在主流瀏覽器中支持挺好的,可是須要兼容 ie6-9
的同窗就得另外尋找方法了。仔細想一想 window.requestAnimationFrame()
跟 setTimeout()
好像有點類似。
window.requestAnimationFrame
回調函數執行次數一般是每秒60次即一秒60幀,將 setTimeout
執行的頻率也設置爲同樣的就好了:
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function (callback) {
return setTimeout(callback, 1000 / 60);
}
}
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
複製代碼
搞定神器 ie6-9
的兼容問題。
第三種寫法使用函數 Element.scrollIntoView()
能夠將選中的元素移動到 可視區域
,可視區域
更多相關知識點能夠看以前的一篇文章 巧用可視區域。
document.querySelector('body')
.scrollIntoView({
behavior: 'smooth',
block: 'start',
})
複製代碼
代碼實現比起第三種簡單了很多,當 css 的 scroll-behavior
被設置時會默認設置 Element.scrollIntoView()
的 behavior
,依舊打開 caniuse 查看兼容性會發現和 window.requestAnimationFrame()
比起來差不了多少,在神器 ie6-9
也有兼容問題。
第四種方法將前面方法進行一個整合,頁面支持 Element.scrollIntoView()
則直接使用第三種方法,若是頁面不支持則使用第二種方法。對於 Element.scrollIntoView()
的支持利用到了 window.getComputedStyle()
也有兼容性問題須要判斷一下:
let scrollToTop;
if (window.getComputedStyle && window.getComputedStyle(document.body).scrollBehavior) {
scrollToTop = () => document.querySelector('body')
.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
} else {
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function (callback) {
return setTimeout(callback, 1000 / 60);
}
}
scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
}
複製代碼
在開發中要注意瀏覽器的兼容性,多使用 caniuse
來幫助咱們參看兼容性狀況。並根據產品的開發需求來書寫代碼,例如不須要兼容 ie6-9
時咱們能夠直接使用 Element.scrollIntoView()
。在剛纔的學習中除了學習了回到頂部外,只需再學習一下獲取元素所在 y
軸座標或者高度就會 一不當心順手
學習了滾動到頁面各處。
在困惑的城市裏總少不了並肩同行的
夥伴
讓咱們一塊兒成長。
點贊
。小星星
。m353839115
。本文原稿來自 PushMeTop