Element.getBoundingClientRect() 回傳元素的大小,以及其相對於可視範圍 (viewport) 的位置。這篇文章將會教你 getBoundingClientRect() 的用法,以及 left、top、right、bottom、width、height 等位置及大小的屬性,並教你如何搭配 window.pageXOffset 和 window.pageYOffset 轉換成絕對位置。

目錄


Rect

getBoundingClientRect() 用法

如果要取得元素 elem 「相對於視窗」的座標,我們可以使用 elem.getBoundingClientRect() 這個方法。他會量測元素包含 border 的大小,並回傳一個 DOMRect 物件,其中包含了 x/y/width/height/top/right/bottom/left 等屬性。

getBoundingClientRect() 屬性說明

  • x/leftelem 左上角的 x 座標
  • y/topelem 左上角的 y 座標
  • widthelem 的寬度,通常等於 offsetWidth
  • heightelem 的高度,通常等於 offsetHeight
  • rightelem 右下角的 x 座標
  • bottomelem 右下角的 y 座標

這些屬性有一些需要注意的事項:

  1. 座標可能是負值,例如:當元素的頂端超出視窗頂端的範圍時,top就會變成負的。
  2. IE 跟 Edge 沒有 xy 屬性,但可用 lefttop
  3. rect.widthrect.height 可能有小數,而 offsetWidth/offsetHeight 會回傳整數。如果需要精確的大小則需要用到 getBoundingClientRect()。
  4. 一般來說 rect.width 等於 elem.offsetWidth,但 elem.offsetWidth 是 layout 的大小,而 width 是實際 rendering 的大小。比如說用了 transform: scale(0.5),寬度 200px 的元素在空間上佔據的位置一樣是 200px (offsetWidth),但是視覺實際看到只有 100px (rect.width)。可以看以下的例子:

See the Pen RwNGJoy by Shubo Chao (@shubochao) on CodePen.


想了解更多 offsetWidth/offsetHeight 細節可以看這篇:

延伸閱讀:[教學] 一次搞懂 clientHeight/clientWidth/offSetHeight/offsetWidth/scrollHeight/scrollWidth/scrollTop/scrollLeft 的區別

用 window.pageXOffset 和 window.pageYOffset 算出絕對位置

很多時候我們需要的是「絕對位置」,也就是元素相對於「文件左上角」的座標,可惜的是瀏覽器並沒有提供一個原生的值可以讓我們使用。

幸好有個很簡單的公式可以幫助我們很方便地計算出絕對位置,那就是「絕對位置座標系和視窗座標系之間的差距」等於捲軸已捲動的長度,也就是 [window.pageXOffset, window.pageYOffset]

所以,絕對位置的計算方式如下:

const x = window.pageXOffset + rect.left;
const y = window.pageYOffset + rect.top;

即使元素在視窗的範圍以外,上面的等式也成立,因為 top/left 是視窗座標系的座標,當超出視窗範圍時會變負值。

想知道更多 pageXOffset/pageYOffset 的細節,可以看這篇:

延伸閱讀:[教學] 一次搞懂 clientHeight/clientWidth/offSetHeight/offsetWidth/scrollHeight/scrollWidth/scrollTop/scrollLeft 的區別

Reference