UNORTHODOX WORKBOOK

BLOG TOPWeb Design外部SVGファイルを非同期で読み込み、インラインのSVGスプライトとして利用する

外部SVGファイルを非同期で読み込み、インラインのSVGスプライトとして利用する

catch-svg-sprite-ajax-load

SVGスプライトを外部ファイルとして読み込みたくて、色々と調べたり試してみたりしていたのですが、外部SVGをAjaxで非同期読み込みするという方法が一番しっくりきたので、その方法を紹介します。

SVGスプライトといっても、CSSで背景画像として表示させるものではなく、HTMLにインラインで表示させるためのSVGスプライトになります。

何もしなくてもuseタグのxlink属性で外部SVGファイルを参照できることは知っていたのですが、IE9+でサポートされてなく、またEdgeでも怪しいとのことだったので、その方法は利用してきませんでした。ポリフィルを使ったフォールバックもあるようですが、そのためだけのフォールバックも何だか気持ちが悪かったので。。

今までやっていた方法

これまではbodyの開始タグすぐ下にsvgタグを置き、その中へ画像ごとにsymbolタグで囲み直したsvgをずらーっと並べuseタグで呼び出す、という方法で表示していました。

HTML

<body>
  <svg style="display:none;">
    <symbol id="twitterIcon" viewBox="0 0 200 200">
      <path d="M246.1,23.7c-9.1,4-18.8,6.7-29,8c10 〜省略〜 39.3,33.8,246.1,23.7z"/>
    </symbol>
    <symbol id="facebookIcon" viewBox="0 0 88 170">
      <path d="M57,170V93h26.6l3.9-31H57V43.1c0-8.7 〜省略〜 H0v31h26v77H57z"/>
    </symbol>
    <symbol id="hatenaIcon" viewBox="0 0 200 200">
      <path d="M85.9,91.8c2.2-1.3,3.3-3.6,3.3-6.8c0 〜省略〜 C79.6,94,83.7,93.1,85.9,91.8z"/>
      <path d="M89.6,111.3c-2.1-1.5-6.1-2.3-11.9-2. 〜省略〜 C92.8,115.3,91.8,112.7,89.6,111.3z"/>
      <path d="M170.4,0H99.8H29.2C13,0,0,13.5,0,29. 〜省略〜 151.3,139.2,146,144.5,139.5,144.5z"/>
    </symbol>
  </svg>
  <div class="wrapper">
    …

SVGタグの部分はdisplay:noneで非表示にします。表示させる時は、使いたい画像のsymbolタグにつけたidを、useタグのxlink属性にセットし表示させます。

HTML

<svg class="icon"><use xlink:href="#twitterIcon"/></svg>

この方法で表示に関しては全く問題ないのですが、画像をコードで羅列しているため視認性が悪く、一つ一つの画像を管理するのが煩わしいのと、複雑な画像だった場合にHTML内がとんでもないことになり、HTMLの管理も面倒になってしまうというデメリットがありました。

そのため、今までは複雑な画像は避け、簡単なアイコンでのみ使用するに留めていました。

xlinkで外部SVGの参照

冒頭で記載した通り、xlinkは外部ファイルを参照できるので、SVGを外部ファイル化し、ファイルパスも含めて属性値に記載しておけば、モダンブラウザでは問題なく表示できます。

HTML

<svg class="icon"><use xlink:href="./assets/images/svg/sprite.svg#twitterIcon"/></svg>

IE11がなくなり、Edgeでの問題が解消されれば、これが一番スマートな方法ですね(さすがにIE11は無視できない&IE9は既にないものとして考えています)。

非同期で読み込む方法

ここからが本題です。

外部SVGファイルの作成

まずは、SVGの外部ファイルを用意します。ファイル名を「sprite.svg」という名前にして、そこにSVGスプライトを作成します。

ここで重要なのは名前空間です。インラインSVGとは異なり通常の「SVGファイル」としなければいけないので、先頭のSVGタグにxmlns属性として必ず名前空間宣言を記載します。最終的にインラインとして挿入するので名前空間は不要と思いがちですが必須です。念のため、version属性も併記しています。

インラインのSVGスプライトが既にあれば、その部分を切り取ってそのまま新規に作成したファイルに貼り付け、名前空間を追加し保存すればOKです。

既存のものがない場合には、下記を参考に作成してみてください。ここではsymbolタグを使用していますが、gタグでも問題ないはずです。必要なのは、名前空間と固有のidです。viewBoxは任意ですが、記載しない場合、呼び出す際に幅と高さを指定し、useで座標を調整する必要があります。

sprite.svg

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="display:none;">
  <symbol id="twitterIcon" viewBox="0 0 200 200">
    <path d="M246.1,23.7c-9.1,4-18.8,6.7-29,8c10 〜省略〜 39.3,33.8,246.1,23.7z"/>
  </symbol>
  <symbol id="facebookIcon" viewBox="0 0 88 170">
    <path d="M57,170V93h26.6l3.9-31H57V43.1c0-8.7 〜省略〜 H0v31h26v77H57z"/>
  </symbol>
  <symbol id="hatenaIcon" viewBox="0 0 200 200">
    <path d="M85.9,91.8c2.2-1.3,3.3-3.6,3.3-6.8c0 〜省略〜 C79.6,94,83.7,93.1,85.9,91.8z"/>
    <path d="M89.6,111.3c-2.1-1.5-6.1-2.3-11.9-2. 〜省略〜 C92.8,115.3,91.8,112.7,89.6,111.3z"/>
    <path d="M170.4,0H99.8H29.2C13,0,0,13.5,0,29. 〜省略〜 151.3,139.2,146,144.5,139.5,144.5z"/>
  </symbol>
</svg>

上記の部分は、svgタグごとそのままHTMLへ挿入されることになるので、style属性にdisplay:noneを指定して非表示にします。svgタグにclassを指定して、CSSでdisplay:noneしても問題無いです。

作成したSVGファイルは、任意の場所にアップロードしておきます。

AjaxでSVGファイルを読み込む

Ajaxは、jQueryのajaxを使っているので、先にjQueryの読み込みが必要になります。下記、url:'./assets/images/svg/sprite.svg'のファイルパスを変更した上で、bodyの終了タグ直前に設置します(外部JS、head内でもOK)。

index.html

<script src="jquery.js"></script>
<script>
  $.ajax({
    type: 'get',
    url: './assets/images/svg/sprite.svg'//ここにパスを入れる(環境に合わせて変更)
  }).done(function(data) {
    var svg = $(data).find('svg');
    $('body').prepend(svg);
  });
</script>
</body>

svgタグごとすべてをjQueryのprependbody要素の先頭に挿入しています。

画像を表示させる時は。同じようにuseタグのxlink属性にそれぞれのidをセットして表示させます。

index.html

<svg class="icon"><use xlink:href="#twitterIcon"/></svg>

あとは、CSSで幅や高さ、色などを調整して完了です。インラインSVGと同じ扱いとなるので、CSSで色々と調整が可能になります。

DEMO

各ブラウザでの表示確認

Chrome、Safari、Firefoxでは問題なく表示できていました。iOSのSafari、AndroidのChromeでも問題なく表示できていましたが、上記のデモはスマホ対応していませんので、表示自体は崩れます。ご了承ください。

IEに関して、IE9では問題なく表示できていました。ただ、IE11とEdgeで確認することができなかったため、もし確認された方がいらっしゃったら教えていただけると助かります。IE9で表示できているので多分大丈夫だとは思いますが。

[追記]
IE11、Edgeでも表示はされているとのご連絡をいただきました。ありがとうございます。ただ、ホバー時のアニメーション等、IEやEdgeならではの不具合(バグ?)はあるようです…。

大きめのSVGを入れて表示してみたりもしましたが、もたつくこともなく表示できていたので、問題なく使える方法かと思います。

SVGスプライトの作成をgulpで自動化

SVGスプライトは手動で作成してもいいのですが、手間が掛かるのと管理が煩わしくなるので、Illustratorで作成したSVGをそのままフォルダに突っ込んで、gulp等で自動化するとより楽になります。

この辺りについて書くと長くなるので、今回はここまでにします。

ABOUT

it's me

長野県北部を拠点にフリーランスとして活動しています。
Webサイトの制作をメインに、グラフィックデザインなどの制作も行っています。 Twitter / GitHub / About

PAGE TOP