要素マージンを含めた width / height を取得するのがちょいと大変だったのでメモ。
html { font-size: 16px; } .div { margin: 0.3rem 0.2rem; // 4.8px 3.2px 相当 border: .3rem solid #000; // 4.8px 相当 width: 6.2rem; // 99.2px 相当 height: 6.2rem; // 99.2px 相当 }
margin を含んだ値で取得できる API は無いっぽい
clientWith
/clientHeight
… border, margin を含まない Int 値offsetWidth
/offsetHeight
… border は含み margin は含まない Int 値getBoundingClientRect
… border は含み margin は含まない Float 値
clientWith / clientHeight は border, margin を含まない
border, margin を含まず、四捨五入で丸められた Int 値が返される
const elm = document.querySelector('.div'); elm.clientWidth; // => 99 Math.round(99.2) elm.clientHeight; // => 99 Math.round(99.2)
offsetWidth / offsetHeight は border を含むが margin は含まない
border を含んだ値で、四捨五入で丸められた Int 値が返される
const elm = document.querySelector('.div'); elm.offsetWidth; // => 112 Math.round(99.2 + 4.8 * 2) elm.offsetHeight; // => 112 Math.round(99.2 + 4.8 * 2)
getBoundingClientRect は border を含むが margin は含まない
border を含んだ値で Float値で取得できる
const elm = document.querySelector('.div'); const { width, height } = elm.getBoundingClientRect(); width; // => 108.78125 ( 99.2 + 4.8 * 2 相当) height; // => 108.78125 ( 99.2 + 4.8 * 2 相当)
margin は style から取得する
window.getComputedStyle(element)
で要素の持つ CSS を取得してその中から margin の値を使う。
const elm = document.querySelector('.div'); const styles = window.getComputedStyle(elm); const {marginTop, marginRight, marginBottom, marginLeft} = styles; // => "4.8px", "3.2px", "4.8px", "3.2px" // 単位を含む文字列で取得されるので parseFloat で数値に変換する Object.fromEntries( Object.entries({ marginTop, marginRight, marginBottom, marginLeft, }) .map(([key, value]) => [key, parseFloat(value) || 0]) ); // => { marginTop: 4.8, marginRight: 3.2, marginBottom: 4.8, marginLeft: 3.2 }
getBoundingClientRect で border を含む width / height を取得して、getComputedStyle で取得できた margin の値を合算する
clientWith
/ clientHeight
, offsetWidth
/ offsetHeight
は丸められた整数値になるので、em
や rem
指定の場合 margin を足すと丸められた少数の誤差の累積で表示されているサイズとの誤差が大きくなりそうなので getBoundingClientRect
を使うのが良さそう。
const getBoundingSize = (element) => { const { width, height } = element.getBoundingClientRect(); return { width, height }; }; const getElementMargin = (element) => { const styles = window.getComputedStyle(element); return ['top', 'right', 'bottom', 'left'].reduce((obj, key) => { return { ...obj, [key]: parseFloat(styles.getPropertyValue(`margin-${key}`)) || 0, }; }); }; const getOuterSize = (element) => { const { top, right, bottom, left } = getElementMargin(element); const { width, height } = getBoundingSize(element); return { width: width + right + left, height: height + top + bottom, }; }; const elm = document.querySelector('.div'); const { width, height } = getOuterSize(elm); width; // => 115.18125 ( 99.2 + 4.8 * 2 + 3.2 * 2 相当) height; // => 118.38125 ( 99.2 + 4.8 * 2 + 4.8 * 2 相当)
example
See the Pen How to get a Element size with margin by KIKIKI (@kikiki_kiki) on CodePen.
パッケージ化してみました。
感想
margin を含んだ値で取得できる API が無いっぽいのは意外だった。
位置を取得できる offsetTop や clientTop も margin を含まないっぽいので、margin を含んだ値を使いたいときは style から取得するしかなさそうな印象でした。
jQuery の outerWidth
, outerHeight
便利だったんですね… (しみじみ…)
[参考]
- hccbe 要素の位置と大きさ
- javascript - Full height of a html element (div) including border, padding and margin? - Stack Overflow
- javascript - Does getBoundingClientRect().width and height includes paddings and borders of element? - Stack Overflow
- Element.getBoundingClientRect() - Web API | MDN
- HTMLElement.offsetHeight - Web API | MDN
- element.clientHeight - Web API | MDN
- Object.fromEntries() - JavaScript | MDN
- .outerHeight() | jQuery API Documentation

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発
- 作者:Ethan Brown
- 発売日: 2017/01/20
- メディア: 単行本(ソフトカバー)

MyProtein マイプロテイン Impact ホエイプロテイン 1kg (限定フレーバー) ミルクティー
- メディア: ヘルスケア&ケア用品