2018年12月20日木曜日

CSS スプライトは表示速度の改善にならない?

SVG の target 属性による画像の切り替えは、1 枚画像による background-potition での方法とは違い、速度や転送量の改善に効果が薄いことがあるようです。

SVG の URLフラグメントによる画像切り替えは、次のようなスタイルを追加した SVG ファイルを用意しておきます。

<svg>
<style>
<![CDATA[
g { display: none; }
g:target { display: inline; }
]]>
</style>
<g id="image1">
<rect x="1" y="6" class="st7" width="30" height="20"/>
</g>

<g id="image2">
<path d="M32,27.313C32,29.891,29.891,32,27.313,32H4.688C2.109,32,0,29.891,0,27.313V4.688C0,2.109,2.109,0,4.688,0 h22.625C29.891,0,32,2.109,32,4.688V27.313z"/>
</g>
</svg>

HTML から target を指定して呼び出します。

<img src="splite-mail-soft.svg#image1" alt="">
<img src="splite-mail-soft.svg#image2" alt="">

当然、画像の読み込みは 1 回限りと思い込んでいましたが、実際はそうではありませんでした。

IE11 (EdgeHTML)

開発者ツールでレンダリングエンジンを Edge に指定。キャッシュ無効。常にサーバーから更新するをオフ。

このファイル splite-mail-soft.svg の後ろには、それぞれ splite-mail-soft.svg#image1 のように異なる URL フラグメントが設定されていますが、URL フラグメントごとに別画像として同じファイルをすべて受信しています。

また、キャッシュを有効にしてもフラグメントごとにサーバーに接続して 304 Not Modified の返事を確認しています。これでは、スプライトにした効果が半減です。

Firefox 64

Firefox も同様に、キャッシュが有効でもサーバーにファイルの更新を確認します。

キャッシュを無効にすると、やはり、別画像として全て受信します。

SRWare Iron 69.0.3600.0 (Blink)

Chrome などの Blink レンダリングエンジンのみ、キャッシュの有効無効関係なく 1 回だけの読み込みで完了します。

本来は、この動作を期待して Splite を作成しています。

最大シェアの Chrome が対応しているので有効な方法ではありますが、SVG の URL フラグメントは画像検索においても不利になるため、相応した速度の改善が欲しいところです。

IE11 は開発終了しているので今後も対応はなし。Edge と Firefox は対応待ちとなります。


この SVG の URL フラグメントを CSS の background-image に指定して、CSS スプライトにできるか?

現在はできます。

いつも技術的に先行している Chrome (Blink) のみ珍しく対応していなかったため使えなかったのですが、少し前に対応されました。

.icon {
background: url(splite-mail-soft.svg#image1) no-repeat;
}
.icon2 {
background: url(splite-mail-soft.svg#image2) no-repeat;
}

この URL フラグメントを background-image にあてる方法は素晴らしいと思い、Chrome の対応を心待ちにしていたのですが、実際にやってみると Illustrator での元絵の作成が結構面倒で、あまり多くの画像を扱うのには適さないのに気が付きました。

実際の Illustrator での作成画面

  • 修正が必要になったときに画像を探すのがたいへんです。1枚絵なら全体を見渡せばさほど苦労することはありません。

  • 該当するレイヤー以外を非表示にしないと編集できません。

  • Illustrator から SVG で出力すると、レイヤー名がご丁寧に書き換えられてしまい、そのまま SVG の id にならずテキストの修正が必要です。

これらのデメリットは、扱う画像がそれほど多くない場合には当てはまらないので、多くても 10 画像程度までなら実用的なテクニックです。