有許多 JavaScript 屬性允許我們讀取有關元素寬度、高度和其他幾何特徵的資訊。
當在 JavaScript 中移動或定位元素時,我們通常需要這些屬性。
範例元素
作為一個展示屬性的範例元素,我們將使用以下給定的元素
<div id="example">
...Text...
</div>
<style>
#example {
width: 300px;
height: 200px;
border: 25px solid #E8C48F;
padding: 20px;
overflow: auto;
}
</style>
它有邊框、內距和捲軸。完整的特徵組。沒有外距,因為它們不是元素本身的一部分,而且它們沒有特殊屬性。
元素看起來像這樣
你可以在沙盒中開啟文件。
上方的圖片展示了元素有捲軸的最複雜案例。一些瀏覽器(不是全部)會保留空間給捲軸,並從內容中取得(標記為上方的「內容寬度」)。
因此,沒有捲軸時內容寬度會是 300px,但如果捲軸寬 16px(寬度可能因裝置和瀏覽器而異),那麼只有 300 - 16 = 284px 剩餘,我們應該將其納入考量。這就是為什麼本章的範例假設有一個捲軸。沒有捲軸時,一些計算會更簡單。
padding-bottom 區域可以填入文字通常內距在我們的插圖中顯示為空白,但如果元素中有許多文字且溢位,那麼瀏覽器會在 padding-bottom 顯示「溢位」的文字,這是正常的。
幾何
以下是幾何屬性的整體圖片
技術上來說,這些屬性的值是數字,但這些數字是「像素」,因此這些是像素量測。
讓我們從元素的外側開始探索屬性。
offsetParent、offsetLeft/Top
這些屬性很少需要,但它們仍然是「最外側」的幾何屬性,所以我們將從它們開始。
offsetParent 是瀏覽器在渲染期間用於計算座標的最接近祖先。
那是以下其中一個的最接近祖先
- CSS 定位(
position是absolute、relative、fixed或sticky),或 <td>、<th>或<table>,或<body>.
屬性 offsetLeft/offsetTop 提供相對於 offsetParent 左上角的 x/y 座標。
在以下範例中,內部的 <div> 有 <main> 作為 offsetParent,而 offsetLeft/offsetTop 從其左上角(180)開始偏移
<main style="position: relative" id="main">
<article>
<div id="example" style="position: absolute; left: 180px; top: 180px">...</div>
</article>
</main>
<script>
alert(example.offsetParent.id); // main
alert(example.offsetLeft); // 180 (note: a number, not a string "180px")
alert(example.offsetTop); // 180
</script>
在下列情況下,offsetParent 會為 null
- 對於未顯示的元素(
display:none或不在文件中)。 - 對於
<body>和<html>。 - 對於具有
position:fixed的元素。
offsetWidth/Height
現在讓我們繼續了解元素本身。
這兩個屬性是最簡單的。它們提供元素的「外」寬度/高度。或者,換句話說,它的完整大小,包括邊框。
對於我們的範例元素
offsetWidth = 390– 外寬度,可以計算為內部 CSS 寬度(300px)加上內距(2 * 20px)和邊框(2 * 25px)。offsetHeight = 290– 外高度。
幾何屬性僅計算顯示的元素。
如果元素(或其任何祖先)具有 display:none 或不在文件中,則所有幾何屬性均為零(或 offsetParent 的 null)。
例如,當我們建立一個元素,但尚未將其插入文件中,或它(或其祖先)具有 display:none 時,offsetParent 為 null,而 offsetWidth、offsetHeight 為 0。
我們可以使用它來檢查元素是否隱藏,如下所示
function isHidden(elem) {
return !elem.offsetWidth && !elem.offsetHeight;
}
請注意,對於在螢幕上但大小為零的元素,此類 isHidden 會傳回 true。
clientTop/Left
在元素內部,我們有邊框。
為了測量它們,有屬性 clientTop 和 clientLeft。
在我們的範例中
clientLeft = 25– 左邊框寬度clientTop = 25– 上邊框寬度
…但要精確地說,這些屬性不是邊框寬度/高度,而是內側相對於外側的相對座標。
差別在哪裡?
當文件從右到左(作業系統為阿拉伯語或希伯來語)時,就會變得明顯。然後,捲軸列不會在右側,而是在左側,然後 clientLeft 也會包含捲軸列寬度。
在這種情況下,clientLeft 將不是 25,而是加上捲軸列寬度 25 + 16 = 41。
以下是以希伯來語為例
clientWidth/Height
這些屬性提供元素邊框內區域的大小。
它們包含內容寬度以及內邊距,但不包含捲軸列
在上面的圖片中,我們首先考慮clientHeight。
沒有水平捲軸列,因此它正好是邊框內所有內容的總和:CSS 高度200px加上頂部和底部內邊距 (2 * 20px),總計240px。
現在是clientWidth - 這裡的內容寬度不是300px,而是284px,因為16px被捲軸列佔用。因此,總和是284px加上左右內邊距,總計324px。
如果沒有內邊距,則clientWidth/Height正好是內容區域,在邊框和捲軸列(如果有)內部。
因此,當沒有內邊距時,我們可以使用clientWidth/clientHeight來獲取內容區域大小。
scrollWidth/Height
這些屬性類似於clientWidth/clientHeight,但它們還包括捲動出去(隱藏)的部分
在上面的圖片中
scrollHeight = 723- 是內容區域的完整內部高度,包括捲動出去的部分。scrollWidth = 324- 是完整的內部寬度,這裡沒有水平捲軸,因此它等於clientWidth。
我們可以使用這些屬性將元素擴展到其完整寬度/高度。
像這樣
// expand the element to the full content height
element.style.height = `${element.scrollHeight}px`;
按一下按鈕以展開元素
scrollLeft/scrollTop
屬性scrollLeft/scrollTop是元素隱藏、捲動出去部分的寬度/高度。
在下面的圖片中,我們可以看到具有垂直捲軸的區塊的scrollHeight和scrollTop。
換句話說,scrollTop是「向上捲動的量」。
scrollLeft/scrollTop可以修改這裡大多數的幾何屬性都是唯讀的,但scrollLeft/scrollTop可以更改,瀏覽器將捲動元素。
如果您按一下下列元素,程式碼 elem.scrollTop += 10 會執行。這會使元素內容向下捲動 10px。
我
1
2
3
4
5
6
7
8
9
將 scrollTop 設定為 0 或大值(例如 1e9)會分別使元素捲動到最上方/最下方。
不要從 CSS 取得寬度/高度
我們剛剛介紹了 DOM 元素的幾何屬性,可用於取得寬度、高度和計算距離。
但我們從 樣式和類別 章節中得知,我們可以使用 getComputedStyle 讀取 CSS 高度和寬度。
那麼,為什麼不使用 getComputedStyle 讀取元素的寬度,如下所示?
let elem = document.body;
alert( getComputedStyle(elem).width ); // show CSS width for elem
為什麼我們應該改用幾何屬性?原因有兩個
-
首先,CSS
width/height取決於另一個屬性:box-sizing,它定義了 CSS 寬度和高度的「意義」。出於 CSS 目的而變更box-sizing可能會導致此類 JavaScript 發生問題。 -
其次,CSS
width/height可能為auto,例如對於內嵌元素<span id="elem">Hello!</span> <script> alert( getComputedStyle(elem).width ); // auto </script>從 CSS 的觀點來看,
width:auto完全正常,但在 JavaScript 中,我們需要計算中可用的精確大小(以px為單位)。因此,這裡的 CSS 寬度毫無用處。
還有一個原因:捲軸。有時,在沒有捲軸的情況下正常運作的程式碼會因為捲軸而出現錯誤,因為在某些瀏覽器中,捲軸會佔用內容的空間。因此,可用於內容的實際寬度小於 CSS 寬度。而 clientWidth/clientHeight 會將其考慮在內。
…但對於 getComputedStyle(elem).width,情況有所不同。有些瀏覽器(例如 Chrome)會傳回實際的內部寬度(減去捲軸),而有些瀏覽器(例如 Firefox)則會傳回 CSS 寬度(忽略捲軸)。這種跨瀏覽器差異就是不使用 getComputedStyle 而依賴幾何屬性的原因。
如果您的瀏覽器為捲軸保留空間(大多數 Windows 瀏覽器都會這麼做),則您可以在下方進行測試。
包含文字的元素具有 CSS width:300px。
在桌上型 Windows 作業系統上,Firefox、Chrome 和 Edge 都會為捲軸保留空間。但 Firefox 顯示 300px,而 Chrome 和 Edge 顯示較小的值。這是因為 Firefox 傳回 CSS 寬度,而其他瀏覽器傳回「實際」寬度。
請注意,所描述的差異僅與從 JavaScript 讀取 getComputedStyle(...).width 有關,在視覺上一切都是正確的。
摘要
元素具有下列幾何屬性
offsetParent– 是最近定位的祖先或td、th、table、body。offsetLeft/offsetTop– 相對於offsetParent左上角的座標。offsetWidth/offsetHeight– 元素的「外」寬度/高度,包含邊框。clientLeft/clientTop– 從左上角外角到左上角內角(內容 + 內距)的距離。對於由左至右的作業系統,它們總是左/上邊框的寬度。對於由右至左的作業系統,垂直捲軸在左側,因此clientLeft也包含其寬度。clientWidth/clientHeight– 內容的寬度/高度,包含內距,但不包含捲軸。scrollWidth/scrollHeight– 內容的寬度/高度,就像clientWidth/clientHeight,但還包括元素中已捲動、不可見的部分。scrollLeft/scrollTop– 元素中已捲動的頂部部分的寬度/高度,從其左上角開始。
除了 scrollLeft/scrollTop 之外,所有屬性都是唯讀的,如果已變更,則會使瀏覽器捲動元素。
留言
<code>標籤,要插入多行程式碼,請將它們包覆在<pre>標籤中,要插入超過 10 行的程式碼,請使用沙盒 (plnkr、jsbin、codepen…)