2016年11月から勧告となったHTML5.1の大きな変更点として<picture>要素とsrcset属性1によるレスポンシブイメージ (responsive images)2の採用がありました。
レスポンシブイメージを利用すればJSやCSSを使わずにブラウザの幅やピクセル密度(Retinaなど)に応じて、異なる画像を読み込む事ができます。
レスポンシブイメージ自体についての詳説は下記をご参照ください。

<img>要素をこんな風に書くと

<img src="lighthouse-160.jpg" alt="灯台"
     sizes="80vw"
     srcset="lighthouse-160.jpg 160w, 
             lighthouse-320.jpg 320w,        
             lighthouse-640.jpg 640w,
             lighthouse-1280.jpg 1280w">

こんな風に画像の出し分けが出来てとても便利です。

レスポンシブイメージのネイティブサポートより

困ったこと


さて、私も早速srcset属性1を使ってこれは便利だと喜んでいたのですが、ある日デザイナーさんにレスポンシブイメージに対して「ロールオーバー3で画像を別な画像に切り替えて欲しい」と言われて困ってしまいました。
よく紹介されている画像切り替え手法はどれもレスポンシブイメージとしっくりこない感じがしたんですよね。

よく使われる画像切り替え方法

  1. CSSスプライトを作りbackground-positionを切替える
  2. CSSでbackground-imageを切替える
  3. CSSでマウスオーバー時<img>要素非表示を指定
  4. <img>要素にonmouseout属性, onmouseover属性を記述
  5. Javascriptで<img>要素のsrc属性を書き換える

よく使われるロールオーバー3画像切り替え方法には上記がありますが、1.はアイコンセットなどでは有効な手法だが、大きな画像には向いていない。2.と3.は事前にロールオーバー用の画像を読み込ませるので、余分な画像を事前ロードさせない(から表示の高速化にも役立つ)というレスポンシブイメージの理念と対立しちゃってる感がある。
5.もHTMLだけで実現できるというメリットが薄くなる感じがするので微妙。…というわけで4. <img>要素にonmouseout属性, onmouseover属性を記述が一番相性が良さそうだと思いました。

本題

onmouseout属性, onmouseover属性でsrcset属性に指定した画像を切り替える

というわけで実装します。

<a href=""> 
<img 
src="/img/sample.png"
srcset="/sample@2x.png 2x, /img/sample.png 1x"
onmouseover="this.setAttribute('srcset','/img/sample_hover@2x.png 2x, /img/sample_hover.png 1x');"
onmouseout="this.setAttribute('srcset','/img/sample@2x.png 2x, /img/sample.png 1x');"
alt="サンプル画像">
</a>

上記のように書けばレスポンシブイメージでも画像切り替えが出来ました!

なお従来は

<a href=""> 
<img 
src="/img/sample.png"
onmouseover="this.src='/img/sample_hover.png'" 
onmouseout="this.src='/img/sample.png'"
alt="サンプル画像">
</a>

のように書けばOKだったので難しくなってはいますね。日々精進!す。


1. 読み方は「ソースセット」。
2. レスポンシブデザイン (RWD) はまた別物です。ややこしいですね。
3. ロールオーバー (roll-over)、マウスオーバー (mouseover)、ホバー (hover)…全部ほぼ同じ意味です。ややこしい。

元記事はこちら

ロールオーバーで画像切り替え レスポンシブイメージ編