有許多 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…)