WordPress以前の時代では、外部画像をimgタグで直リンクするというのはよくある話でした。最近では、リンク先のサーバーに禁止されてできなくなっています。
アフィリエイトの場合、画像の直リンクを推奨しているところもあります。商品画像などを入れ替えたり、廃止商品になったりしたときに画像を使ってほしくない時に、サーバーの画像を入れ替えたり消したりすることで、ユーザーごとに対応せずに一括で処置できるからです。
しかし、外部画像を直リンクする時に問題となるのが、imgタグのwidthとheightのパラメータです。widthとheightはCLS対策として必須になっています。Wordpress内部の画像であれば勝手にwidthとheightが追加されますが、外部の画像については対象外です。
外部画像のサイズが固定であればまだ対策できますが、画像ごとにサイズが違うといちいち調べて手打ちするか、スクリプトで処置しなければ対応できなくなります。
この記事では、外部画像のimgタグのwithとheigthをどうやって調べて追加するかについてまとめています。
PHPを使ってwidthとheightを取得
WordPressサイトの場合は、PHPが使えます。PHPには画像サイズを取得する便利な関数があります。
getimagesize関数を使うと、画像のwidthとheightが取得できます。

getimagesize使用例
$url = "hogehoge.com/img.jpg";
echo '<img '.getimagesize($url)[3].'src="'.$url.'"/>';
getimagesizeの問題点
使用する回数が増えると、外部との通信が増えて処置遅延が増えてきます。
10とか20個ぐらいになると数秒単位でサイトの表示が遅くなります。
使用できる回数は、1ページ当たり2~3個が限度ではないかと思います。
Javascriptを使ってwidthとheightを取得
Javascriptを使っても外部画像のwidthとheightを取得できます。そのまま、DOMを書き換えればimgタグのwidthとheightを設定することができます。
この方法は、サイトの表示速度に影響は出ないのですが、Lazyload対処でsrcが書き換えられたimgタグとの相性が悪いような気がします。
また、外部画像をlazyload前に読み込むのも効果を打ち消している気がします。
//関数定義
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);
});
}
参考:https://into-the-program.com/get-img-add-width-height-auto/
CSSだけで対応する
imgタグのwidthとheightは本当に必要なのでしょうか?
PageSpeedInsightの対策としてwidthとheightは必要ですが、CLSを悪化させないためだけであれば、外部画像のwidthとheightの正確な値は必要ありません。
画像を読み込む前後で要素の高さが変わらなければCLSは悪化しません。
そのための対策としては、以下の2つを行えばよいです。
- 画像をabsoluteにして、親要素いっぱいに広げる
- 親要素のアスペクト比を固定する(以下の例だと4:3)
- 画像を縮小したい場合は、画像の表示エリアを調整。
親要素の高さもしくは画像のアスペクト比で調整する
アスペクト比の例
アスペクト比 | パーセント |
16:9 | 56.25% |
4:3 | 75% |
3:2 | 66.666% |
2:1 | 50% |
<figure>
<img src="xxx" width="100" height="100"/>
</figure>
figure{
max-height: 500px; /*画像の幅を制限する*/
}
figure:before{
padding-top: 75%; /*アスペクト比を指定*/
content: "";
display: block;
}
figure img{
width: 100%;
height: 100%;
max-width: none;
max-height: none;
position: absolute;
top: 0;
object-fit: contain;
}
imgタグはposition:absoluteなのでサイズが”0″扱いになり、画像サイズはレイアウト崩れへの影響力が無くなります。
figureは子要素のimgタグが無くなり、figureの高さが決まらなくなります。そこで疑似要素を追加して、padding-topで高さを決めます。
imgタグは親要素全体に広がるので、画像の高さもそこで決まります。そうなると、外部画像のimgタグのwidthとheightはどんな値でもCLSに影響しなくなります。
まとめ
今回ご紹介したCSSを使う方法では、外部画像を直リンクして表示する際にwidthとheightの正確な値を知る必要はありません。
もしどうしても必要だとするなら処理速度やLazyload処理と相談して、javascriptかPHPで対応するしかないでしょう。
今回紹介したCSSによる方法を使わない場合に、widthやheightを固定値で決め打ちするとCLSも悪化しますし、目次からスムーススクロールする際にも飛び先がずれてしまう問題が起きやすいです。