【JavaScript】img要素の画像サイズを取得してwidth・heightを自動追加する
※本ページのリンクにはプロモーションが含まれています。
こんにちは、Ryohei(@ityryohei)です!
本記事では、JavaScriptでimg要素の画像サイズを取得してwidth・height属性を自動で追加する方法をご紹介しています。
img要素のsrcから画像のサイズを取得してwidth・height属性を自動で指定したいんだけど、良い方法ないかな?
上記の疑問にお答えします。
では、解説していきます。画像サイズを取得してimg要素に設定する方法
画像サイズを取得する方法は複数ありますが、本記事ではImage
オブジェクトで取得する方法で解説します。Image
オブジェクトに画像を設定して、設定した画像のサイズ(width
・height
)を取得するには下記のように記述します。
const image = new Image(); image.src = '画像のパス'; image.width; //画像の横幅を取得 image.height; //画像の高さを取得
実際にページ内のimg
要素を全て取得してwidth
・height
の設定までを組んだスクリプトがこちら。
//ページ内のimg要素をすべて取得 const imgs = document.getElementsByTagName('img'); //Imageオブジェクトをインスタンス化 const image = new Image(); //img要素の数だけ繰り返し処理 for (const img of imgs) { //img要素からsrc属性の値を取得 //Imageオブジェクトのsrcプロパティに代入 image.src = img.getAttribute('src'); //画像の横幅をimg要素のwidth属性の値に設定 img.setAttribute('width', image.width); //画像の高さをimg要素のheight属性の値に設定 img.setAttribute('height', image.height); }
一応上記のスクリプトでページ内のimg要素から画像を取得し、width
・height
を自動で追加するところまで実現できます。
試しにPicsumさんからダミーの画像をお借りして、動作を確認してみます。
HTML
<div id="app"> <img src="https://picsum.photos/id/1008/1920/1080" alt=""> <img src="https://picsum.photos/id/656/1280/720" alt=""> <img src="https://picsum.photos/id/646/1366/768" alt=""> </div>
JavaScriptは先ほどご紹介したものをそのまま使いまして……。
完成したデモがこちら!
See the Pen Img width height auto1|JavaScript by ryohei (@intotheprogram) on CodePen.
環境によってはちゃんとwidth
・height
が設定されている方もいらっしゃると思いますが、何度か再読み込みをすると下記のように値が設定されます。
<div id="app"> <img src="https://picsum.photos/id/1008/1920/1080" alt="" width="0" height="0"> <img src="https://picsum.photos/id/656/1280/720" alt="" width="0" height="0"> <img src="https://picsum.photos/id/646/1366/768" alt="" width="0" height="0"> </div>
width
・height
が0に設定されています。これでは自動で追加する意味がないどころか、デメリットしかないですね。
なぜこのようなことが起こるのでしょうか。
調べたところ、原因はすごく単純でした。
画像が読み込まれる前にサイズを取得するから
img
要素が指定された画像パスから実際に画像を読み込む前に、画像サイズを取得していたため、値が0になっていました。読み込まれていない画像のサイズを参照しているわけですから、当然結果は0になります。なので、画像が読み込まれた後にサイズを取得するように処理を改善する必要があります。
Promiseで画像を非同期に読み込む
Promise
は非同期処理の最終的な結果を表すオブジェクトです。Promise
で画像の読み込みが完了した後に画像サイズを取得してimg
要素に設定することで前項のような結果を回避することができます。
実際にPromise
で作り直した処理がこちら!(HTMLに変更はありません。)
//関数定義 const myFunc = function(src){ //Promiseオブジェクトを生成して返す return new Promise(function(resolve, reject){ //Imageオブジェクトを生成 const image = new Image(); //読み込む画像を設定(関数の引数で取得した画像パスを代入) image.src = src; //onloadで画像読み込み完了後に処理 image.onload = function(){ //成功時にthenの処理へ resolve(image); } //onerrorで画像読み込みエラー時に処理 image.onerror = function(error){ //失敗時にcatchの処理へ reject(error); } }); } //ページ内のimg要素を取得 const imgs = document.getElementsByTagName('img'); //img要素の数だけ繰り返し処理 for (const img of imgs) { //img要素のsrc属性の値を取得 const src = img.getAttribute('src'); //関数実行 myFunc(src) //読み込みが完了した(画像が設定された)Imageオブジェクトを受け取って処理 .then(function(res){ //img要素のwidth属性に値を設定 img.setAttribute('width', res.width); //img要素のheight属性に値を設定 img.setAttribute('height', res.height); }) //画像読み込みエラー時の処理 .catch(function(error){ console.log(error); }); }
下記デモにおいてもきちんとwidth
・height
属性に値が設定されています。
See the Pen Img width height auto2|JavaScript by ryohei (@intotheprogram) on CodePen.
これでimg要素にwidth
・height
属性を自動で追加することができます。
width・height属性が設定されていないimg要素にのみ自動追加する
前項でご紹介した内容は、img
要素にwidth
・height
属性が設定されている場合も再度画像サイズを取得し、属性値を上書きします。もしwidth
・height
属性が設定されていないimg
要素にのみ適用したい場合は、下記のようにif
文を追記してください。
HTML
<div id="app"> <img src="https://picsum.photos/id/1008/1920/1080" alt="" width="500" height="500"> <img src="https://picsum.photos/id/656/1280/720" alt=""> <img src="https://picsum.photos/id/646/1366/768" alt=""> </div>
JavaScript
//関数定義 const myFunc = function(src){ //Promiseオブジェクトを生成して返す return new Promise(function(resolve, reject){ //Imageオブジェクトを生成 const image = new Image(); //読み込む画像を設定(関数の引数で取得した画像パスを代入) image.src = src; //onloadで画像読み込み完了後に処理 image.onload = function(){ //成功時にthenの処理へ resolve(image); } //onerrorで画像読み込みエラー時に処理 image.onerror = function(error){ //失敗時にcatchの処理へ reject(error); } }); } //ページ内のimg要素を取得 const imgs = document.getElementsByTagName('img'); //img要素の数だけ繰り返し処理 for (const img of imgs) { //img要素のsrc属性の値を取得 const src = img.getAttribute('src'); //関数実行 myFunc(src) //読み込みが完了した(画像が設定された)Imageオブジェクトを受け取って処理 .then(function(res){ //【追加】img要素にwidth属性が設定されていなければ処理 if(!img.hasAttribute('width')){ //img要素のwidth属性に値を設定 img.setAttribute('width', res.width); } //【追加】img要素にheight属性が設定されていなければ処理 if(!img.hasAttribute('height')){ //img要素のheight属性に値を設定 img.setAttribute('height', res.height); } }) //画像読み込みエラー時の処理 .catch(function(error){ console.log(error); }); }
実行結果
See the Pen Untitled by ryohei (@intotheprogram) on CodePen.
これでwidth
・height
属性が設定されていないimg
要素にのみwidth
・height
を自動で追加することができます。
最後に
JavaScriptのレンダリング結果がHTMLと同様にSEOにおいて評価されるようになったことからわかるように、JavaScriptにおける処理結果も考慮されるようになりました。もちろん静的に記述しておいた方が無難ですが、昔のサイトであったり数が多い場合などはJavaScriptのレンダリングに委ねるのも良いかもしれないですね。
以上、JavaScriptでimg要素の画像サイズを取得してwidth・heightを自動追加する方法のご紹介でした!
JavaScriptを基礎からしっかりと学びたい方へ
下記の参考書がおすすめです。私がJavaScript入門時に購入した書籍で、基礎から応用まで多様なサンプルを用いて解説されています。ページ数は多いですが、内容が伴っているのですらすら読めます。腰を据えて学びたい方に最良の一冊となっています。