我們如何找出瀏覽器視窗的寬度和高度?我們如何取得文件的完整寬度和高度,包括捲動出去的部分?我們如何使用 JavaScript 捲動頁面?
對於這種類型的資訊,我們可以使用根文件元素 document.documentElement
,它對應到 <html>
標籤。但還有其他方法和特殊情況需要考慮。
視窗的寬度/高度
若要取得視窗寬度和高度,我們可以使用 document.documentElement
的 clientWidth/clientHeight
例如,這個按鈕顯示你的視窗高度
window.innerWidth/innerHeight
瀏覽器也支援像 window.innerWidth/innerHeight
之類的屬性。它們看起來就像我們想要的,為什麼不改用它們呢?
如果存在捲軸,且它佔用了一些空間,clientWidth/clientHeight
會提供不包含捲軸的寬度/高度(扣除捲軸)。換句話說,它們會傳回文件的可見部分的寬度/高度,也就是內容可用的部分。
window.innerWidth/innerHeight
包含捲軸列。
如果有一個捲軸列,並且佔用了一些空間,那麼這兩行會顯示不同的值
alert( window.innerWidth ); // full window width
alert( document.documentElement.clientWidth ); // window width minus the scrollbar
在大部分情況下,我們需要可用的視窗寬度,以便在捲軸列(如果有)中繪製或定位某些內容,因此我們應該使用 documentElement.clientHeight/clientWidth
。
DOCTYPE
很重要請注意:當 HTML 中沒有 <!DOCTYPE HTML>
時,頂層幾何屬性可能會稍微不同。可能會發生奇怪的事情。
在現代 HTML 中,我們應該始終撰寫 DOCTYPE
。
文件寬度/高度
理論上,由於根文件元素是 document.documentElement
,並且包含所有內容,因此我們可以將文件的完整大小測量為 document.documentElement.scrollWidth/scrollHeight
。
但在該元素上,對於整個頁面,這些屬性無法按預期工作。在 Chrome/Safari/Opera 中,如果沒有捲動,則 documentElement.scrollHeight
甚至可能小於 documentElement.clientHeight
!很奇怪,對吧?
為了可靠地獲取完整的文檔高度,我們應該採用這些屬性的最大值
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
alert('Full document height, with scrolled out part: ' + scrollHeight);
為什麼這樣?最好不要問。這些不一致性來自於古代,而不是「智慧」邏輯。
獲取當前捲動
DOM 元素在它們的 scrollLeft/scrollTop
屬性中具有它們當前的捲動狀態。
對於文件捲動,document.documentElement.scrollLeft/scrollTop
在大多數瀏覽器中都能正常工作,除了基於 WebKit 的舊瀏覽器,例如 Safari(錯誤 5991),在這些瀏覽器中,我們應該使用 document.body
而不是 document.documentElement
。
幸運的是,我們根本不必記住這些特殊性,因為捲動可以在特殊屬性 window.pageXOffset/pageYOffset
中使用
alert('Current scroll from the top: ' + window.pageYOffset);
alert('Current scroll from the left: ' + window.pageXOffset);
這些屬性是唯讀的。
window
屬性 scrollX
和 scrollY
使用由於歷史原因,這兩個屬性都存在,但它們是相同的
window.pageXOffset
是window.scrollX
的別名。window.pageYOffset
是window.scrollY
的別名。
捲動:scrollTo、scrollBy、scrollIntoView
要使用 JavaScript 捲動頁面,必須完全建立其 DOM。
例如,如果我們嘗試使用 <head>
中的腳本來捲動頁面,它將不起作用。
可以透過變更 scrollTop/scrollLeft
來捲動一般元素。
我們可以使用 document.documentElement.scrollTop/scrollLeft
對頁面執行相同的操作(Safari 除外,Safari 應改用 document.body.scrollTop/Left
)。
或者,有一個更簡單的通用解決方案:特殊方法 window.scrollBy(x,y) 和 window.scrollTo(pageX,pageY)。
-
scrollBy(x,y)
方法會將頁面捲動到相對於目前位置。例如,scrollBy(0,10)
會將頁面向下捲動10px
。下面的按鈕示範這個功能
-
scrollTo(pageX,pageY)
方法會將頁面捲動到絕對座標,讓可見部分的左上角座標為(pageX, pageY)
,相對於文件的左上角。這就像設定scrollLeft/scrollTop
一樣。若要捲動到最開頭,我們可以使用
scrollTo(0,0)
。
這些方法對所有瀏覽器都以相同的方式運作。
scrollIntoView
為了完整性,讓我們介紹另一個方法:elem.scrollIntoView(top)。
呼叫 elem.scrollIntoView(top)
會捲動頁面以使 elem
可見。它有一個參數
- 如果
top=true
(這是預設值),則頁面將捲動到使elem
出現在視窗頂端。元素的上緣將與視窗頂端對齊。 - 如果
top=false
,則頁面將捲動到使elem
出現在底部。元素的下緣將與視窗底部對齊。
下面的按鈕會捲動頁面,將其自身定位在視窗頂端
而這個按鈕會捲動頁面,將其自身定位在底部
禁止捲動
有時我們需要讓文件「無法捲動」。例如,當我們需要用一個需要立即注意的大訊息覆蓋頁面時,我們希望訪客與該訊息互動,而不是與文件互動。
若要讓文件無法捲動,只需設定 document.body.style.overflow = "hidden"
即可。頁面會「凍結」在目前的捲動位置。
試試看
第一個按鈕凍結捲動,而第二個按鈕則解除凍結。
我們可以使用相同的技術來凍結其他元素的捲動,而不仅仅是 `document.body`。
此方法的缺點是捲軸條會消失。如果它佔用了一些空間,那麼現在這個空間是空的,而內容會「跳動」以填滿它。
這看起來有點奇怪,但如果我們在凍結前後比較 `clientWidth`,就可以解決這個問題。如果它增加了(捲軸條消失了),那麼在 `document.body` 中新增 `padding` 來取代捲軸條,以保持內容寬度相同。
摘要
幾何
-
文件可見部分的寬度/高度(內容區域寬度/高度):`document.documentElement.clientWidth/clientHeight`
-
整個文件的寬度/高度,包括捲動出的部分
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
捲動
-
讀取目前的捲動:`window.pageYOffset/pageXOffset`。
-
變更目前的捲動
window.scrollTo(pageX,pageY)
– 絕對座標,window.scrollBy(x,y)
– 相對於目前位置捲動,elem.scrollIntoView(top)
– 捲動以使 `elem` 可見(與視窗的頂部/底部對齊)。
評論