[70-5] 複数のSVGを1つにまとめて個別に呼び出す SVGスプライト
最終更新日:2017年11月15日 (初回投稿日:2017年05月08日)複数のSVG画像のコードを1つにまとめておいて、HTML上で個別に呼び出すことを、 SVGスプライト(SVG Sprite)というと言うんだそうで、今回はこれを使ってみます。
SVGはコードが長くなりがちなので、同じ図形を何度も使う場合、使用する箇所ごとにいちいち同じコードを書くのは面倒。
そこで、SVGをまとめて書いておき、図形を貼りたい箇所で呼び出すようにすれば、何度も同じコードを書かなくて済み、編集もラクになるというわけです。
アイコンなどページ内で同じものを何度も使うなら、SVGスプラウトにしたほうが便利です。
SVGスプライトは、<body>直下にジカに書く方法と、SVGを外部ファイルにして呼び出す方法があるそうなんですが、今回はせっかくなので外部ファイルにする方法をやってみます。
今回使用する要素 | <symbol> 〜 </symbol> <use />(終了タグはありません。XMLなので最後に/が必要) |
---|
複数の図形を1まとめに作る(Illustrator)
今回のサンプルはこちらです(クリックで別ウィンドウで開きます)
今回は、レストランのメニューなどで使う食品のアレルゲンのアイコンを作ってみました。
Illustratorで アイコンが全部出来上がったら、アートボードはアイコンのサイズにし、各アイコンを重ねてしまいます。
このほうが、図形の基点(左上)が全部 x=0 y=0 になって呼び出しやすいから。
各アイコンはレイヤーを分けて、レイヤー名をちゃんとつけておきます。
Illustrator で SVG を描くときのアートボードの編集などは
[70-1] svg要素でベクターグラフィクスを埋め込もう をご覧ください。
書き出したSVGファイルを編集する
Illustratorで画像ができたら、SVGファイルに書き出します。
(書き出し方は [70-1] svg要素でベクターグラフィクスを埋め込もう をご覧ください)
Illustratorのファイルと同名の、拡張子が「.svg」になったファイルができますので、これをテキストエディタとか Dreamweaverやらで開いてコードを編集します。
編集の要点は、
1. <svg>要素のみにして、余計なものは削除
2. <svg>要素の属性を整理する(名前空間宣言を残す)
3. 各アイコン画像は<g>要素でグルーピングされているが、これを<symbol>に書き換える
4. <symbol>要素に viewBox属性を書いておく
といった感じです。
<svg>要素のみにして、余計なものは削除
Illustratorが書き出したファイルがこちら↓ 主役の<svg>要素の上のハイライト部分を削除します。(<svg>〜</svg>だけを残すってことです)
Illustratorが書き出したSVGファイル
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="47px" height="50px" viewBox="0 0 47 50"
enable-background="new 0 0 47 50" xml:space="preserve">
<g id="milk">
<path fill="#D0A195" d="M47,..."/>
<!-- パスなどのコード。長いので略 -->
</g>
<g id="wheat">
<path fill="#D0A195" d="M47,..."/>
<!-- 長いので略 -->
</g>
<g id="egg">
<path fill="#D0A195" d="M47,..."/>
<!-- 長いので略 -->
</g>
</svg>
<svg>要素のみにして編集したのがこちら↓(他にも<symbol>要素が登場したりしていますが順に説明します)
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" class="allergen-icon">
<symbol id="milk" viewBox="0 0 47 50">
<!-- パスなどのコード。長いので略 -->
</symbol>
<symbol id="wheat" viewBox="0 0 47 50">
<!-- 長いので略 -->
</symbol>
<symbol id="egg" viewBox="0 0 47 50">
<!-- 長いので略 -->
</symbol>
</svg>
冒頭の <svg>要素の属性を整理します。(上記コードの1行目)
「名前空間宣言(xmlns="http://www.w3.org/2000/svg")」は必須です。無いと無理。
バージョンは無くても表示しましたが、一応残しました。
他の、サイズや位置に関する属性は、アイコンごとに指定するので削除しました。
「名前空間宣言」は、ブラウザに「このXMLはSVGだ」と宣言するもの。SVGはXML言語なので。
HTML5上に直接この<svg>を置く場合は「名前空間宣言」が無くても表示されますが、外部ファイルにするときは「名前空間宣言」がないとダメでした。画像が表示されません。
★<svg>要素の属性については [70-1] svg要素でベクターグラフィクスを埋め込もうをご覧ください。
ここではクラス名を入れていますが、これは後でCSSで「display:none」にするため。
(ここでジカに「style="display:none"」って書いてもOKです)display:none の理由は後で説明。
<g>要素を<symbol>要素に書き換え、viewBox属性もここに
各アイコンのかたまりである <g>要素を <symbol>要素に書き換えます。
編集後のSVGファイル
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" class="allergen-icon">
<symbol id="milk" viewBox="0 0 47 50">
<!-- パスなどのコード。長いので略 -->
</symbol>
<symbol id="wheat" viewBox="0 0 47 50">
<!-- 長いので略 -->
</symbol>
<symbol id="egg" viewBox="0 0 47 50">
<!-- 長いので略 -->
</symbol>
</svg>
<g id="milk"> 〜 </g> を、<symbol id="milk"> 〜 </symbol> にする、という要領です。
Illustratorでの描画時につけたアイコンの名前(レイヤー名)が id名になっているので、どの<g>要素かすぐ分かります。
さらに、<symbol id="milk" viewBox="0 0 47 50"> といったかんじで、冒頭の<svg>要素に入っていた viewBox属性を <symbol>要素に入れます。
(Illustratorで <svg>要素に書き出されていたものをコピペするだけです。数値は「0 0」は図形の基点、「47 50」は幅と高さ)
こうすることで 各アイコンは HTML上で好きなサイズにCSSで指定できるようになります。
<symbol>要素にする利点
<symbol>要素は、その名のとおり図形を「シンボル」にする要素。
複数のシンボルをまとめて1つのシンボルとして扱ったりもできます。
<symbol>要素の中身はそのままでは表示されず、<use>要素で呼び出すことで表示します。
<g>要素も <use>要素で呼び出して使うことができますが、
<symbol>要素の利点は viewBox属性を使えること。
viewBox属性を指定しておけば、呼び出したところで自由にサイズを変えられます。
<g>要素ではviewBox属性が使えないので、<g>要素で指定したサイズが固定サイズになります。
HTML上に SVGファイルを呼び出す
出来上がった 外部SVGファイルを、HTMLの<body>直下に呼び出します。
呼び出すには 外部SVGファイルのパス(URL)を使います。
今回のサンプルではこのように「img」フォルダ内に外部SVGファイルを入れときました。
jQueryを使う方法
jQueryを使うので、先にjQueryを読み込むのを忘れずに。
以下のコードを <head>部に入れればOK。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<!--jqueryのバージョンは3系でもOK。古い1系でも使えました-->
<script>
$.ajax({
type: 'get',
url: './img/allergen_icon.svg' <!--外部SVGファイルのパスを書きます-->
}).done(function(data) {
var svg = $(data).find('svg');
$('body').prepend(svg); <!--<body>要素の先頭にSVGファイルが読み込まれます-->
});
</script>
</body>
このJavaScriptコードは、こちらのサイトを参考にさせていただきました。ありがとうございます。
UNORTHODOX WORKBOOK|外部SVGファイルを非同期で読み込み、インラインのSVGスプライトとして利用する
こちらのサイトのように↑、JavaScriptは <body>内に書いてもOK。
私は jQueryは<head>部に置くことが多いので、どうせなら全部<head>部に入らないかなと、やってみたところ大丈夫でした。
PHPならたった1行
WordPressを使ってるサイトなら、PHPで簡単に外部SVGファイルを読み込めます。
PHPの「include_once( )」を使って <body>直下に1行を追加するだけ。
★WordPressだと include_once(" ") というカタチにするそうです。(かっこ内でダブルクォーテーションマークでファイル名を囲む)
WordPressの場合の外部SVGの読み込み
<body>
<?php include_once("images/allergen_icon.svg"); ?>
<!--ここでは外部SVGファイルは「images」フォルダに入れています-->
このコードを書くファイルは、<body>タグがあるファイル。たいてい「header.php」ですね。
で、外部SVGファイルのパスは相対パスで書くのがミソ。これ重要。
絶対パス(http://で始まるやつ)で書くと読み込まれませんでした。WordPressの仕様でしょうか。
例えば、上のサンプルコードの場合は、ファイルの位置関係はこのようになっています。
コードを書く「header.php」からの相対位置で、外部SVGファイル「allergen_icon.svg」を指定するのでパスは「images/allergen_icon.svg」になります。
「images」に入れず「header.php」と同じディレクトリなら、パスは「allergen_icon.svg」だけ。
外部SVGファイルの <svg>要素を display:none にする理由
上記の2つの方法(jQueryを使う方法・PHP)とも、外部SVGに書かれたコード(<svg> 〜 </svg>)が、HTML の <body>のすぐ下に書き出されます。
でも各アイコンは<symbol>要素にしているので、そこでは図形は表示されない。
だけど、図形分のスペースは空くんです。なのでその分ごそっと下がってレイアウトが変になっちゃう。
そこで、外部SVG内の <svg>要素に display:none を指定しておくというわけです。display:none はスペースも詰めてくれます。
このように、外部SVGファイルの内容は <body>タグの直下に書き出されますので、WordPressの場合では全ページにコードが読み込まれることになります。(静的なHTMLの場合なら、読み込ませたHTMLファイルのみにSVGが書き出されます)
ですので「SVGスプライト」は、全ページ共通に使う図形(SNSアイコンとか)に限定すべき。
単一ページでのみ使う図形なら、SVGスプライトにしないで普通にSVGを貼り付けたほうが無難です。
SVG画像を使いたいところに<use>要素で呼び出す
次はいよいよ 各アイコンを HTML内で使っていきます。
SVGの図形を呼び出すには <use>要素を使います。
<svg><use xlink:href="#id名"/></svg>というカタチで利用。この<svg>要素の位置に図形が表示されます。
id名は、各図形の <symbol>要素につけた id名です。
サンプルでは、下記のように書いています。
サンプルのHTML抜粋
<div>
<h3>キッズハンバーグ<span>(乳・小麦・卵は使用しておりません)</span></h3>
<svg class="al-icon"><use xlink:href="#milk"/></svg>
<svg class="al-icon"><use xlink:href="#wheat"/></svg>
<svg class="al-icon"><use xlink:href="#egg"/></svg>
</div>
呼び出すときは超シンプルなコードでOK。同じアイコンを何度でも呼び出せます。
サンプルでは各<svg>要素にクラス名(class="al-icon")をつけました。これはサイズなどを CSSで指定するため。
CSSでサイズなどを指定
各アイコンのサイズ指定などはCSSで行います。
サンプルのCSSは下記のようになっています。
svg.allergen-icon {display:none} /*SVGスプライト内のsvgを display:none にしておきます*/
svg.al-icon { /*HTML上に配置する各アイコンの指定です*/
margin:0 10px 0 0;
width:104px; /*サイズの指定(拡大になるけどキレイ)*/
height:110px;
padding:5px; /*paddingはドロップシャドウのために指定しています*/
-webkit-filter: drop-shadow(2px 2px 2px #ccc); /*ドロップシャドウ(ちょっと古めのブラウザ用)*/
filter: drop-shadow(2px 2px 2px #ccc)} /*ドロップシャドウ*/
各アイコンの元のサイズは 47×50pxです。CSSでのサイズ指定は拡大していますが、SVGなので拡大してもキレイです。
<symbol>要素には viewBox属性が使えるので、このように呼び出した後でサイズ変更ができます。
ドロップシャドウをつけることもできます(7、8行目)
これは CSS3の filterプロパティを使っています。(IE11は filterプロパティには未対応です)
サンプルの「drop-shadow(2px 2px 2px #ccc)」という「( )」内の4つの値は、
「x方向のズレ y方向のズレ ぼかし幅 シャドウの色」です。
x, y方向のズレはマイナスの値も使えます。色指定は16進数指定じゃなくても何でもいけます。
色指定は [14-4] 色指定について(16進数, 色名, 10進数, HSL, accessibility)をご覧ください。
Chromeや Operaの場合、<svg>要素にドロップシャドウを指定しても、中身のSVGアイコンそのものにシャドウがつくので、それが<svg>要素にピッタリサイズになってる(<symbol>要素のviewBox属性のため)のでシャドウが見えなくなってしまいます。
それを防ぐために <svg>要素に paddingの指定をしました(6行目)。
次回予告
SVGについては、今回で終わりです。
時系列では次回から またCSSに戻ります。
displayプロパティが終わったところなので、次は visibilityプロパティをやろうと思っています。
時系列だと HTMLの話、CSSの話とあちこち飛んでわかりにくいですね。
インデックスから記事を選んでいただけますので、ご利用ください。
はじめてのHTML INDEX
はじめてのCSS INDEX
- 関連記事
-
- [72] デバイスに合わせた画像を表示できる picture要素
- [71] img要素の srcset属性で画像を切り替えよう
- [70-5] 複数のSVGを1つにまとめて個別に呼び出す SVGスプライト
- [70-4] JavaScriptライブラリで作るSVGモーフィングアニメーション
- [70-3] CSSだけで作る SVGのドローイングアニメーション
- [70-2] SVGフィルターを使ってみた
- [70-1] svg要素でベクターグラフィクスを埋め込もう
- (ちょっとメモ)API って何だ?(HTML5 の API について)
- (ちょっとメモ)CanvasサイズをCSS3のvw, vhで取得してみたけど...
- [69-14] Canvasのアニメーションの基本を見てみよう
- (ちょっとメモ)Canvasでグラフを自動生成する「flotr2」が便利
- [69-13] Canvasで画像データをURLとして取得しよう
- (ちょっとメモ)Canvasで画像をランダムに描くサイト背景をWordPressで使ってみた
- [69-12] Canvasをサイトの背景に使おう
- [69-11] Canvasでビットマップを操作しよう(ビットマップの明度や色調の変更)
初心者にも使いやすい(と思う)レンタルサーバー
「初心者ですがレンタルサーバーはどこがいい?」というご質問をよくいただきます。
自由にファイルをアップロードできる自分のサーバがあると便利ですよね。ローカル環境じゃなくサーバ上で試してみたい時がありますからね。
私が使っているのは、
スターサーバーや ロリポップ!
です。どちらも管理画面がわかりやすく、マニュアルも充実していて、料金も安い。どちらもライトプラン以上で WordPress が使えます。
初心者が始めやすいサーバだと思います。
ちょっと料金は高いけど、さくらのレンタルサーバや、エックスサーバー
は、やはり老舗なのでおすすめです。
両方とも高スペックでコスパが良く、老舗でユーザーが多いので、質問する場がたくさんあります。初心者だけど仕事でサーバが欲しい場合は、安心なのではないかと思います。
スポンサーリンク