Javascript Window 大小和滾動(dòng)

2023-02-17 10:54 更新

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

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

窗口的 width/height

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


不是 ?window.innerWidth/innerHeight?

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

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

window.innerWidth/innerHeight 包括了滾動(dòng)條。

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

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

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

?DOCTYPE? 很重要

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

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

文檔的 width/height

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

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

為了可靠地獲得完整的文檔高度,我們應(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)前滾動(dòng)

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

對(duì)于文檔滾動(dòng),在大多數(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)前滾動(dòng)信息:

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

這些屬性是只讀的。

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

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

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

滾動(dòng):scrollTo,scrollBy,scrollIntoView

重要:

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

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

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

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

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

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

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

scrollIntoView

為了完整起見,讓我們?cè)俳榻B一種方法:elem.scrollIntoView(top)。

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

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

禁止?jié)L動(dòng)

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

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

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

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

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

總結(jié)

幾何:

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

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

滾動(dòng):

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)