yasuda

jQueryでウィンドウサイズによって画像を切り替える

レスポンシブ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に変更しました。

スクリプトはこのような処理をしています。

  1. ウィンドウサイズを取得して、それに応じて処理を開始
  2. attr()でsrc属性値を取得する
  3. replace()でファイル名の末尾を置換する
  4. リサイズ(ウィンドウサイズが変更)されたら、そのたびに処理を実行する

以下の変数は案件に応じて変更してください。

  • `$elem`は画像の切り替えを適応する要素
  • spは狭い幅(スマホなど)で使用するファイル名のキーワード
  • pcは広い幅(PCなど)で使用するファイル名のキーワード
  • replaceWidthは画像を切り替えるウィンドウサイズ(px)

置換対象とするファイル名のキーワードは_sp.のようにしてドットを加えています。簡易的ですが、これで_specialのようなファイル名まで置換されてしまうのを防いでいます。.js-image-switchを指定していると、置換はされませんが処理自体は実行されてしまうので、必要なければclass属性は外してください。

リサイズ時の処理はdebounceというJavaScriptのパターンを使用して、処理を実行するまでのタイミングを遅らせています。この場合はリサイズが終わって0.2秒経ったときに処理を実行します。画像を多く使用しているページでは特に有効だと思います。

まとめ

末尾に_spをつけるといった画像の命名規則に気をつける必要がありますが、比較的簡単に画像のレスポンシブ化ができる方法だと思います。

切り替わるパターンを増やしたい場合はif文に条件を加えれば実装できますが、このスクリプトでは画像をすべてのパターンで用意しておく必要があるので、手間や保守性を考えると2種類までにしておくのがいいのかなと思います。

HTML5のPictureタグを使った切り替え方法の記事も書きました。

レスポンシブイメージのポリフィル「Picturefill.js」でブレイクポイントによって画像を切り替える

参考ページ

新しいウェブ体験を作ろう TAMのPWA開発
お問い合わせはこちら