CATEGORY

SVG

SVG】最近流行りの SVG スプラッシュ!じゃない、スプライト

SVG - ソフトクリーム ベリー グッド

1,085 PV

レスポンシブデザインを触っていると、必ず一度はお目にかかる SVG アイコン。
img要素として画像のように挿入する方法や font を割り当てる方法など、色んな使い方がありますが、今回は外部 SVG ファイルを Ajax で読み込み、直接 SVG スプライトとして取り扱う方法を紹介します。

もともと僕は CSS でfillを設定するために単色の SVG は直接ソース内に書き込んでいたのですが、ソースのボリュームが馬鹿にならない点や、かなりソースの初めの方(<body>直後など)で読み込まなければならない SEO との相性の悪さに不満があったため、この方法に行きつきました。

まずは SVG スプライトデータを準備

svg.html

<svg display="none" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
    <symbol id="siteLogo" viewBox="0 0 226 147.17">
    <g>
    <path d="M64.667,2.001c-13.666,6.333-18.333,~29.835,45.834,29.835z"/>
    <path d="M80.977,97.893c-3.776-0.197-5.~81.236,116.874,81.236z"/>
    <path d="M152.76,97.318c-3.77,0.262-5.656,~87.67,152.743,90.885,152.76,97.318z"/>
    <path d="M199.333,95.836c-1.438,0-2.842,~135.168,199.333,135.168z"/>
    </g>
    </symbol>
    
    <symbol id="instaIcon" viewBox="0 0 512 512">
    <g>
    <path d="M256,49.471c67.266,0,75.233,~4.369,324.418,4.08,256,4.08L256,4.08z"/>
    <path d="M256,126.635c-71.446,0-129.365,~302.377,339.974,256,339.974z"/>
    <circle cx="390.476" cy="121.524" r="30.23"/>
    </g>
    </symbol>
</defs>
</svg>

SVG のデータは、Adobe illustrator で吐き出したものを編集して使用しています。
編集時の注意点は以下のような感じ。

  1. <svg></svg> で必ずくくる

    太字の部分はほぼ定型文のような感じです。display:noneを設定しておかないと、ajax で読み込んだ場所にスプライトが全部表示されてしまいますので、お気を付けください。空の SVG ボックスが表示されます。
    ※<defs> タグでくくっていたので、SVG 要素は表示されませんでした(。-人-。)

  2. <defs></defs> は必須ではないけどくくっておく

    <defs>タグは<symbol>などの実際には描写されない図形の定義をまとめておく論理タグです。今後のアクセシビリティなどのために僕は書くようにしています。

  3. <symbol> には個別に id をつける

    <symbol>がそれぞれの SVG データになっているので、個別に id を付けておかないとスプライトとして機能しません。

  4. viewBox の座標問題

    viewBoxは SVG を保存した際 illustrator が勝手に設定してくれるので、
    その設定をいじらないようにしておけば基本オッケーなのですが、アートボードの座標(0 , 0)が起点になっていないと正常に表示されないことが多いです。
    この問題に関しては、
    → 新規ファイル作成 → SVG アイテムをコピー&ペースト → SVG で保存
    の手順を踏みなおすことによって、ちゃんとした座標の SVG ファイルを作ることができます。

SVG スプライトデータに関しては、ざっとこんなところです。
Adobe illustrator で吐き出したデータには元々fillが設定してあるのですが、僕が使うタイミングではほぼ毎回fillも設定していたため SVG 上からは消しました。

jQuery の Ajax を使って取り込もう

$(function(){
    $.ajax({
        type:'get',
        url:'~/****/svg.html',
        dataType:'html'
    }).done(function(data){
        $('body').prepend(data);
    }).fail(function(data){
        console.log('error');
    });
});

先程作った SVG スプライトファイルをソースの一部として<body>直後に挿入します。ソースの最後の方ではなく<body>直後である理由は、読み込まれていない SVG 要素を描写できないブラウザがあったためです。

<svg> タグを使って呼び出すぜーい

あとは<img>なんかと同じように、

<svg class="siteLogoSvg">
    <title>サイトロゴ</title>
    <use xlink:href="#siteLogo"/>
</svg>

<use>タグにxlink:hrefidを指定して呼び出してあげればオッケーです。
<svg>タグにclassidを指定しておけば、CSSを使ってfillやサイズを指定することもできます。またサイズを指定する場合はwidthheightの両方を指定してあげないと、思い通りの表示になりません。※ちなみに何も指定しなかった場合は、viewBoxで設定されているサイズのSVGがドーンと表示されます。

おまけ:SVG にリンクを設定しよう

<svg>タグで読み込んだ SVG にリンクを貼る正しいやり方は<svg>タグ内でのリンク設定なのですが、そのやり方だと塗りのない部分は反応しなくなってしまいます。細い線などを使った SVG だとまともにクリックできないことがほとんどです。

<svg class="siteLogoSvg">
<a xlink:href="/home">
    <title>サイトロゴ</title>
    <use xlink:href="#siteLogo"/>
</a>
</svg>

そこで正式なやり方ではないのですが、僕は直接 SVG 要素を<a>タグでくくる方法を使っています。この場合対象の SVG 要素にはdisplay:blockwidthheightの指定が必要になるのですが、<img>タグで SVG を読み込んだような挙動を実現することができます。

※ SVG はdisplay:blockwidthheightを指定しなかった場合サイズ不定のグラフィック扱いになるため、正常なリンク範囲が設定できずに苦しみます。主に下部の無駄な余白など。。。

<a href="/home">
<svg class="siteLogoSvg">
    <title>サイトロゴ</title>
    <use xlink:href="#siteLogo"/>
</svg>
</a>

こんな感じで今は使っていますが、またブラウザのバージョンが変わってくると別の使い方が出てくるかもしれません。というか、いつになったら

<svg class="siteLogoSvg">
    <use xlink:href="~/****/svg.html#siteLogo"/>
</svg>

でみんなが読み込める時代になってくれるんだろうか。。。。

今回お世話になったサイトさん

CATEGORY : SVG

TAGS : |

GO TOP