Javascript Window 大小和滾動

2023-02-17 10:54 更新

我們?nèi)绾握业綖g覽器窗口(window)的寬度和高度呢?我們?nèi)绾潍@得文檔(document)的包括滾動部分在內(nèi)的完整寬度和高度呢?我們?nèi)绾问褂?JavaScript 滾動頁面?

對于此類信息,我們可以使用與 <html> 標(biāo)簽相對應(yīng)的根文檔元素 document.documentElement。但是還有其他方法和特性需要考慮。

窗口的 width/height

為了獲取窗口(window)的寬度和高度,我們可以使用 document.documentElement 的 clientWidth/clientHeight


不是 ?window.innerWidth/innerHeight?

瀏覽器也支持像 window.innerWidth/innerHeight 這樣的屬性。它們看起來像我們想要的,那為什么不使用它們呢?

如果這里存在一個(gè)滾動條,并且滾動條占用了一些空間,那么 clientWidth/clientHeight 會提供沒有滾動條(減去它)的 width/height。換句話說,它們返回的是可用于內(nèi)容的文檔的可見部分的 width/height。

window.innerWidth/innerHeight 包括了滾動條。

如果這里有一個(gè)滾動條,它占用了一些空間,那么這兩行代碼會顯示不同的值:

alert( window.innerWidth ); // 整個(gè)窗口的寬度
alert( document.documentElement.clientWidth ); // 減去滾動條寬度后的窗口寬度

在大多數(shù)情況下,我們需要 可用 的窗口寬度以繪制或放置某些東西。也就是說,在滾動條內(nèi)(如果有)。所以,我們應(yīng)該使用 documentElement.clientHeight/clientWidth。

?DOCTYPE? 很重要

請注意:當(dāng) HTML 中沒有 <!DOCTYPE HTML> 時(shí),頂層級(top-level)幾何屬性的工作方式可能就會有所不同??赡軙霈F(xiàn)一些稀奇古怪的情況。

在現(xiàn)代 HTML 中,我們始終都應(yīng)該寫 DOCTYPE。

文檔的 width/height

從理論上講,由于根文檔元素是 document.documentElement,并且它包圍了所有內(nèi)容,因此我們可以通過使用 documentElement.scrollWidth/scrollHeight 來測量文檔的完整大小。

但是在該元素上,對于整個(gè)文檔,這些屬性均無法正常工作。在 Chrome/Safari/Opera 中,如果沒有滾動條,documentElement.scrollHeight 甚至可能小于 documentElement.clientHeight!很奇怪,對吧?

為了可靠地獲得完整的文檔高度,我們應(yīng)該采用以下這些屬性的最大值:

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);

為什么這樣?最好不要問。這些不一致來源于遠(yuǎn)古時(shí)代,而不是“聰明”的邏輯。

獲得當(dāng)前滾動

DOM 元素的當(dāng)前滾動狀態(tài)在其 scrollLeft/scrollTop 屬性中。

對于文檔滾動,在大多數(shù)瀏覽器中,我們可以使用 document.documentElement.scrollLeft/scrollTop,但在較舊的基于 WebKit 的瀏覽器中則不行,例如在 Safari(bug 5991)中,我們應(yīng)該使用 document.body 而不是 document.documentElement。

幸運(yùn)的是,我們根本不必記住這些特性,因?yàn)槲覀兛梢詮?nbsp;window.pageXOffset/pageYOffset 中獲取頁面當(dāng)前滾動信息:

alert('當(dāng)前已從頂部滾動:' + window.pageYOffset);
alert('當(dāng)前已從左側(cè)滾動:' + window.pageXOffset);

這些屬性是只讀的。

我們也可以從 ?window? 的 ?scrollX? 和 ?scrollY? 屬性中獲取滾動信息

由于歷史原因,存在了這兩種屬性,但它們是一樣的:

  • ?window.pageXOffset? 是 ?window.scrollX? 的別名。
  • ?window.pageYOffset? 是 ?window.scrollY? 的別名。

滾動:scrollTo,scrollBy,scrollIntoView

重要:

必須在 DOM 完全構(gòu)建好之后才能通過 JavaScript 滾動頁面。

例如,如果我們嘗試通過 <head> 中的腳本滾動頁面,它將無法正常工作。

可以通過更改 scrollTop/scrollLeft 來滾動常規(guī)元素。

我們可以使用 document.documentElement.scrollTop/scrollLeft 對頁面進(jìn)行相同的操作(Safari 除外,而應(yīng)該使用 document.body.scrollTop/Left 代替)。

或者,有一個(gè)更簡單的通用解決方案:使用特殊方法 window.scrollBy(x,y) 和 window.scrollTo(pageX,pageY)。

  • 方法 scrollBy(x,y) 將頁面滾動至 相對于當(dāng)前位置的 (x, y) 位置。例如,scrollBy(0,10) 會將頁面向下滾動 10px。
  • 方法 scrollTo(pageX,pageY) 將頁面滾動至 絕對坐標(biāo),使得可見部分的左上角具有相對于文檔左上角的坐標(biāo) (pageX, pageY)。就像設(shè)置了 scrollLeft/scrollTop 一樣。

這些方法適用于所有瀏覽器。

scrollIntoView

為了完整起見,讓我們再介紹一種方法:elem.scrollIntoView(top)。

對 elem.scrollIntoView(top) 的調(diào)用將滾動頁面以使 elem 可見。它有一個(gè)參數(shù):

  • 如果 ?top=true?(默認(rèn)值),頁面滾動,使 ?elem? 出現(xiàn)在窗口頂部。元素的上邊緣將與窗口頂部對齊。
  • 如果 ?top=false?,頁面滾動,使 ?elem? 出現(xiàn)在窗口底部。元素的底部邊緣將與窗口底部對齊。

禁止?jié)L動

有時(shí)候我們需要使文檔“不可滾動”。例如,當(dāng)我們需要用一條需要立即引起注意的大消息來覆蓋文檔時(shí),我們希望訪問者與該消息而不是與文檔進(jìn)行交互。

要使文檔不可滾動,只需要設(shè)置 document.body.style.overflow = "hidden"。該頁面將“凍結(jié)”在其當(dāng)前滾動位置上。

我們還可以使用相同的技術(shù)來凍結(jié)其他元素的滾動,而不僅僅是 document.body

這個(gè)方法的缺點(diǎn)是會使?jié)L動條消失。如果滾動條占用了一些空間,它原本占用的空間就會空出來,那么內(nèi)容就會“跳”進(jìn)去以填充它。

這看起來有點(diǎn)奇怪,但是我們可以對比凍結(jié)前后的 clientWidth。如果它增加了(滾動條消失后),那么我們可以在 document.body 中滾動條原來的位置處通過添加 padding,來替代滾動條,這樣這個(gè)問題就解決了。保持了滾動條凍結(jié)前后文檔內(nèi)容寬度相同。

總結(jié)

幾何:

  • 文檔可見部分的 width/height(內(nèi)容區(qū)域的 width/height):
  • ?document.documentElement.clientWidth/clientHeight?

  • 整個(gè)文檔的 width/height,其中包括滾動出去的部分:
  • let scrollHeight = Math.max(
      document.body.scrollHeight, document.documentElement.scrollHeight,
      document.body.offsetHeight, document.documentElement.offsetHeight,
      document.body.clientHeight, document.documentElement.clientHeight
    );

滾動:

  • 讀取當(dāng)前的滾動:?window.pageYOffset/pageXOffset?。
  • 更改當(dāng)前的滾動:
    • ?window.scrollTo(pageX,pageY)? —— 絕對坐標(biāo),
    • ?window.scrollBy(x,y)? —— 相對當(dāng)前位置進(jìn)行滾動,
    • ?elem.scrollIntoView(top)? —— 滾動以使 ?elem? 可見(?elem? 與窗口的頂部/底部對齊)。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號