【JavaScript】サイズ・座標 取得チートシート(Chrome)

# サイズ

## clientTop / clientLeft / clientHeight / clientWidth

### clientTop
【概要】要素の上ボーダーのピクセル幅。上マージン、上パディングは含まれません。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用

### clientLeft
【概要】要素の左ボーダーのピクセル幅です。 左マージン、左パディングを含みません。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用

### clientHeight
【概要】要素内部の高さ。パディングを含みますが、水平スクロールバーの高さ・ボーダー・マージンを含まない。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用

### clientWidth
【概要】要素内部の幅。パディングを含みますが、垂直スクロールバーの幅、ボーダー、マージンを含みません。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/bfe31953-0ef5-aecc-1368-045d4c81d3e5.png)

## offsetHeight / offsetWidth

### offsetHeight
【概要】要素のレイアウトの高さ。パディング、要素の水平スクロールバーの幅、ボーダーを含めます。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用

### offsetWidth
【概要】要素のレイアウト幅。パディング、要素の垂直スクロールバーの幅、ボーダーを含めます。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/b08f60ff-52cd-190f-dc77-3320e0f0ae44.png)

## scrollWidth/scrollHeight

### scrollHeight
【概要】overflowした画面上に表示されていないコンテンツを含む要素の内容の高さを表します。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用
【備考】スクロールバーが表示されていない場合は、offsetHeightと同じになる。（borderが含まれる。）

### scrollWidth
【概要】overflowした画面上に表示されていないコンテンツを含む要素の内容の幅を表します。
【値】ピクセル(整数)
【書き込みの可否】読み込み専用
【備考】スクロールバーが表示されていない場合は、offsetWidthと同じになる。（borderが含まれる。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/afebca9c-4480-e34f-3753-3611abb4dc77.png)

# 座標

## offsetParent, offsetLeft/Top

### offsetParent
offsetParentはオフセット座標の基準となる要素です。
offsetParentはターゲットの要素の状況によって異なり、次の条件を満たす要素が返されます。
#### (1)テーブル要素内の場合
ターゲットがテーブル要素内にある場合は、ターゲットを囲う直近のtd要素、th要素、またはtable要素がoffsetParentとなります。

- td要素の子孫の場合は、直近の祖先tdがoffsetParentとなります。

```html
<body>
  <table>
    <tbody>
      <tr>
        <th>ID</th>
        <th>名前</th>
        <th>苗字</th>
      </tr>
      <tr>
        <td>
          <p>1</p>
        </td>
        <td>
          <p>山田</p>
        </td>
        <td>太郎</td>
      </tr>
      <tr>
        <td>
          <p>2</p>
        </td>
        <td>
          <p>
            <span id="target">田中</span>
          </p>
        </td>
        <td>
          <p>一郎</p>
        </td>
      </tr>
    </tbody>
  </table>
</body>
```
```
target.offsetParent
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/e549c845-ee32-5faf-bbdd-51fface5ec9c.png)

- th要素の子孫の場合は、直近の祖先tdがoffsetParentとなります。

```html
<body>
  <table>
    <tbody>
      <tr>
        <th>ID</th>
        <th>
          <p>
            <span id="target">名前</span>
          </p>
        </th>
        <th>苗字</th>
      </tr>
      <tr>
        <td>
          <p>1</p>
        </td>
        <td>
          <p>山田</p>
        </td>
        <td>太郎</td>
      </tr>
      <tr>
        <td>
          <p>2</p>
        </td>
        <td>
          <p>田中</p>
        </td>
        <td>
          <p>一郎</p>
        </td>
      </tr>
    </tbody>
  </table>
</body>
```
```
target.offsetParent
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/bc61bedb-f2c5-f27b-05f6-28bb373dfc53.png)

- th要素の子孫またはtd要素の子孫出ない場合は、直近の祖先table要素がoffsetParentとなります。

```html
<body>
  <table>
    <tbody>
      <tr>
        <th>ID</th>
        <th id="target">
          名前
        </th>
        <th>苗字</th>
      </tr>
      <tr>
        <td>
          <p>1</p>
        </td>
        <td>
          <p>山田</p>
        </td>
        <td>太郎</td>
      </tr>
      <tr>
        <td>
          <p>2</p>
        </td>
        <td>
          <p>田中</p>
        </td>
        <td>
          <p>一郎</p>
        </td>
      </tr>
    </tbody>
  </table>
</body>
```

```
target.offsetParent
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/e0db4e9f-6b4c-6919-29d6-0f7d9d534791.png)

#### (2)テーブル要素内ではない場合
テーブル要素内でない場合は、直近の祖先の「動的に位置が調整される要素」となります。
「動的に位置が調整される要素」とは、
- position:relative 
- position:absolute
- position:fixed

のいずれかが指定されている要素となります。

下記のhtmlの場合、target1、target2、target3のoffsetParentは図の様になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/47e0448c-e79e-15cb-5aa0-72510e6f9def.png)

#### (3)上記(1)(2)に当てはまらない場合
body要素がoffsetParentとなります。

## offsetLeft/Top
offsetLeft/TopはそれぞれoffsetParentへの相対的なleft、topの距離を返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/c7952e24-2c98-9f8f-44ee-0799df49b2ee.png)

## getBoundingClientRect() / getClientRects()

### getBoundingClientRectメソッド
 getBoundingClientRectメソッドは、要素の寸法と、そのビューポートに対する相対位置を保持するDOMRectオブジェクトを返します。

今下記のようなHTMLがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/fa661328-b6fa-fc79-3dc7-d27ae405abd9.png)

```html
<html>

<body>
  <div id="parent">
    <div id="button">ボタン</div>
    <div id="target"></div>
  </div>
</body>

<script>
  function consoleRects() {
    console.log("【getBoundingClientRect】", target.getBoundingClientRect());
  }
  button.addEventListener("click", consoleRects);
</script>

</html>

<style>
  body {
    margin: 0;
  }

  #parent {
    position: relative;
    height: 2000px;
    width: 2000px;
  }

  #target {
    position: absolute;
    top: 120px;
    left: 130px;
    height: 50px;
    width: 100px;
    border: solid 30px;
    margin: 5px;
  }

  #button {
    position: fixed;
    border: solid 1px;
    margin: 5px;
    z-index: 10;
  }
</style>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/c9beb0aa-58e2-b19a-08ba-a3daacb62ed5.png)
※スペースの関係上parentは実際より短く表現しています。実際はもっと上下とも長いと考えてください。

リロードしてスクロールせずにボタンをクリックしてみます。
すると下記の様に出力されます。

```
DOMRect {
  bottom: 235
  height: 110
  left: 135
  right: 295
  top: 125
  width: 160
  x: 135
  y: 125
}
```

それぞれviewportからの相対距離を以下で取得してきています。(px)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/aabd9aef-2175-f042-a686-25464797fcc2.png)

以下の様に画面を水平スクロールして、左側が画面から飛び出した場合を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/0a37d299-0dbd-5277-1749-cca51239d373.png)

ボタンをクリックすると以下の様に出力されました。

```
DOMRect {
  bottom: 235
  height: 110
  left: -94
  right: 66
  top: 125
  width: 160
  x: -94
  y: 125
}
```
これは下記の様に計算された結果となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/38e47027-8e4d-be8f-2033-46800b1fc855.png)

getBoundingClientRectメソッドはターゲットの要素のviewport（可視範囲）における相対位置によって返す値が変化します。
viewportからはみ出した部分は、 **「負の距離」** として計算されます。
これは垂直方向に相対位置が変化した場合も同様にbottom、topが変化します。
height、widthは変化しません。

例えば以下の様に、完全に左上にはみ出した場合は、top、bottom、right、left全てが負の距離となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/e51f7886-85d8-98a5-d0d6-64770aba841f.png)

### getClientRectsメソッド
複数行のインライン要素 （例えば複数行にまたがる <span> 要素）に行ごとのRectsオブジェクトを返します。

例えば以下のようなhtmlがあります。

```html
<html>

<body>
  <div id="parent">
    <div id="button">ボタン</div>
    <div id="box">
      <span id="target">あいうえおかきくけこさしすせそ
      </span>
    </div>
  </div>
</body>

<script>
  function consoleRects() {
    console.log("【getBoundingClientRect】", target.getBoundingClientRect());
    //console.log("【getClientRects】", target.getClientRects());

  }
  button.addEventListener("click", consoleRects);
</script>

</html>

<style>
  body {
    margin: 0;
  }

  #parent {
    position: relative;
    height: 2000px;
    width: 2000px;
  }

  #box {
    position: absolute;
    top: 120px;
    left: 130px;
    height: 100px;
    width: 100px;
    border: solid 30px;
    margin: 5px;
  }

  #button {
    position: fixed;
    border: solid 1px;
    margin: 5px;
    z-index: 10;
  }
</style>
```
getBoundingClientRectは上記の説明の通りtarget要素のDOMRectオブジェクトを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/7d91e5cc-46b5-3a21-f026-54822838ed65.png)

consoleRectsコメントアウトを切り替えて、getClientRectsの返り値を出力してみます。
```js
  function consoleRects() {
    console.log("【getBoundingClientRect】", target.getBoundingClientRect());
    //console.log("【getClientRects】", target.getClientRects());
  }
```

以下の様にDOMRectオブジェクトを3つ持つ配列が返されました。

```
DOMRectList {
  0: DOMRect {
    bottom: 150
    height: 16
    left: 140
    right: 236
    top: 134
    width: 96
    x: 140
    y: 134
  }
  1: DOMRect {
    bottom: 174
    height: 16
    left: 140
    right: 236
    top: 158
    width: 96
    x: 140
    y: 158
  }
  2: DOMRect {
    bottom: 198
    height: 16
    left: 140
    right: 188
    top: 182
    width: 48
    x: 140
    y: 182
  {
}
```

getClientRectsは、インライン要素が折り返されている場合、それぞれの行のDOMRectを計算して、配列として返されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/5fe93572-ab03-d383-9ada-9fc7415f5eb3.png)

以下の記事に続きます。

[【JavaScript】サイズ・座標 取得 〜 実践編 ＜ツールチップの実装＞ 〜](https://qiita.com/sho_U/items/a2874f375e0e2132f5c6)