レスポンシブWebデザインではおもにウィンドウサイズによってレイアウトを変更していきますが、画像はHTMLとCSSだけでは最適化するのが難しいです。
background
プロパティであればメディアクエリで切り替えられますが、img
タグで指定したい場合には使えません。また、srcset
属性を使えばウィンドウサイズや解像度によって画像を切り替えることができますが、IEはまったく対応していないので専用のプラグインを読み込む必要があります。
そこで使用しているのが、jQueryで画像ファイル名の一部を置換して表示する画像を切り替える方法です。
ウィンドウサイズを検知して画像ファイル名を置換する
HTML側は.js-image-switch
のついているimg
要素のファイル名を以下のように変更して表示を切り替えていきます(ここでは仮に768pxとします)。.js-image-switch
にはCSSでスタイルを指定せず、jQueryで要素を特定する目的だけに使用します。
画像ファイルは末尾に_sp
と_pc
のついた2種類を用意して、マークアップ時には_sp
を記述しておきます。
<!-- 768px未満 -->
<img src="image_sp.png" alt="" class="js-image-switch">
<!-- 768px以上 -->
<img src="image_pc.png" alt="" class="js-image-switch">
スクリプトは以下のようになります。
$(function() {
// 置換の対象とするclass属性。
var $elem = $('.js-image-switch');
// 置換の対象とするsrc属性の末尾の文字列。
var sp = '_sp.';
var pc = '_pc.';
// 画像を切り替えるウィンドウサイズ。
var replaceWidth = 768;
function imageSwitch() {
// ウィンドウサイズを取得する。
var windowWidth = parseInt(window.innerWidth);
// ページ内にあるすべての`.js-image-switch`に適応される。
$elem.each(function() {
var $this = $(this);
// ウィンドウサイズが768px以上であれば_spを_pcに置換する。
if(windowWidth >= replaceWidth) {
$this.attr('src', $this.attr('src').replace(sp, pc));
// ウィンドウサイズが768px未満であれば_pcを_spに置換する。
} else {
$this.attr('src', $this.attr('src').replace(pc, sp));
}
});
}
imageSwitch();
// 動的なリサイズは操作後0.2秒経ってから処理を実行する。
var resizeTimer;
$(window).on('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
imageSwitch();
}, 200);
});
});
※ 2018年3月13日: 横幅の取得をwidth
からinnerWidth
に変更しました。
スクリプトはこのような処理をしています。
- ウィンドウサイズを取得して、それに応じて処理を開始
attr()
でsrc属性値を取得するreplace()
でファイル名の末尾を置換する- リサイズ(ウィンドウサイズが変更)されたら、そのたびに処理を実行する
以下の変数は案件に応じて変更してください。
`$elem`
は画像の切り替えを適応する要素sp
は狭い幅(スマホなど)で使用するファイル名のキーワードpc
は広い幅(PCなど)で使用するファイル名のキーワードreplaceWidth
は画像を切り替えるウィンドウサイズ(px)
置換対象とするファイル名のキーワードは_sp.
のようにしてドットを加えています。簡易的ですが、これで_special
のようなファイル名まで置換されてしまうのを防いでいます。.js-image-switch
を指定していると、置換はされませんが処理自体は実行されてしまうので、必要なければclass
属性は外してください。
リサイズ時の処理はdebounceというJavaScriptのパターンを使用して、処理を実行するまでのタイミングを遅らせています。この場合はリサイズが終わって0.2秒経ったときに処理を実行します。画像を多く使用しているページでは特に有効だと思います。
まとめ
末尾に_sp
をつけるといった画像の命名規則に気をつける必要がありますが、比較的簡単に画像のレスポンシブ化ができる方法だと思います。
切り替わるパターンを増やしたい場合はif
文に条件を加えれば実装できますが、このスクリプトでは画像をすべてのパターンで用意しておく必要があるので、手間や保守性を考えると2種類までにしておくのがいいのかなと思います。
HTML5のPicture
タグを使った切り替え方法の記事も書きました。
レスポンシブイメージのポリフィル「Picturefill.js」でブレイクポイントによって画像を切り替える