JavaScriptで<img>の元の大きさを取得する (naturalWidth/naturalHeight)
HTMLImageElement
(<img>
) のwidth
/height
は、実際の表示サイズに引っ張られて値が変化する。(明示的に指定してても引っ張られる!)- 元の大きさを取得したければ
naturalWidth
/naturalHeight
を見る。
経緯と結論から
レスポンシブ対応してるサイト作ってて、レイアウトから画像がはみ出さないよう <img>
に max-width:100%
とか設定してたら、縮小されてる時に img.width
に依存するJavaScriptがうまく動かなかった。
確認してみたところ、どうも HTMLImageElement
の width
/height
には原寸ではなく実際の表示サイズがセットされてる模様。しかも、明示的に指定してても、必ず実際の表示サイズがセットされてるっぽい。
元の大きさを取得したければ、以下のように naturalWidth
/naturalHeight
を見る。
var img = document.getElementById('id-of-img');
console.log(img.naturalWidth);
console.log(img.naturalHeight);
実験1: 普通に取得
↓の多幸感に溢れた画像は、原寸が 256 × 256 px。

この <img>
タグの大きさを、以下のようにJavaScriptで取得する。
<img src="img.gif" alt="" id="img1" />
var img = document.getElementById('img1');
console.log(img.width); // -> 256
console.log(img.height); // -> 256
console.log(img.naturalWidth); // -> 256
console.log(img.naturalHeight); // -> 256
console.log(img.style.width); // -> (カラ文字)
console.log(img.style.height); // -> (カラ文字)
img
の width
/height
および naturalWidth
/naturalHeight
は、もちろん 256。
style
は設定していないので、img.style
の width
/height
はカラ文字となり、取得できなかった。
実験2: 間接的に縮小して取得
↓の画像は、さっきと同じ画像。ただし <img>
の外側のボックスをスタイルシートで 128 × 128px にしたうえで、<img>
に style
で max-width:100%
を指定しているので、小さく表示されてる。

<img>
に style
で width
/height
を直接指定せず、遠回しに表示上のサイズを変えてるのがミソ。この <img>
タグの大きさを、先程と同様にJavaScriptで取得する。
<div style="width:128px; height:128px;">
<img src="img.gif" alt="" id="img2" style="max-width:100%;" />
</div>
var img = document.getElementById('img2');
console.log(img.width); // -> 128
console.log(img.height); // -> 128
console.log(img.naturalWidth); // -> 256
console.log(img.naturalHeight); // -> 256
console.log(img.style.width); // -> (カラ文字)
console.log(img.style.height); // -> (カラ文字)
img
の width
/height
が 128 となることに注目! 実際の表示サイズが反映されてる。
naturalWidth
/naturalHeight
なら元の大きさ 256 を取得できる。
実験3: 間接的に縮小&明示的に指定して取得
じゃあ <img>
の width
/height
をHTML上で明示的に指定してたらどうなるの? というわけで、先程の条件に追記して実験。
<img>
の外側のボックスをスタイルシートで 128 × 128px にする。<img>
にstyle
でmax-width:100%
を指定する。<img>
のwidth
/height
に 200 を指定する。

ハチャメチャ。max-width
のせいで縦長になっちゃってる。そしてこの <img>
タグの大きさを、先程と同様にJavaScriptで取得すると……。
<div style="width:128px; height:128px;">
<img src="img.gif" alt="" id="img3" style="max-width:100%;" width="200" height="200" />
</div>
var img = document.getElementById('img3');
console.log(img.width); // -> 128
console.log(img.height); // -> 200
console.log(img.naturalWidth); // -> 256
console.log(img.naturalHeight); // -> 256
console.log(img.style.width); // -> (カラ文字)
console.log(img.style.height); // -> (カラ文字)
console.log(img.getAttribute('width')); // -> "200"
console.log(img.getAttribute('height')); // -> "200"
*明示的に指定したにも関わらず、img
の width
が 128 になってる。*ということは、HTMLImageElement
の width
/height
には、本当に実際の表示サイズがセットされてるらしい。
一応、HTML上で明示的に設定した width
/height
も getAttribute()
で取得できたけど、HTMLの <img>
とJavaScriptの HTMLImageElement
は同一視しないほうがよさそうだ。