アイコンフォントからSVGへ!より手軽にベクター画像を表示しよう
ベクター画像を表示する際とっても便利なSVG。名前を聞いたことのある方も多いのではないでしょうか?SVG自体は10年以上前から存在するのですが、HTML5の普及とともに多くのブラウザーでサポートされるようになり、今年に入ってから徐々に見かける機会が増えてきました。今回はそんなSVGにフォーカスしようと思います。
SVGってなに?
SVG(Scalable Vector Graphics)はIllustratorで作成したようなベクター画像を表示する技術です。Web上で一般的に使われる画像形式であるJPEGやPNGなどのビットマップ形式とは違い、ベクター形式の画像は、拡大縮小しても画質が劣化しません。
Appleがレティナディスプレイを発表して以来、デザイナー達は画像をどのように高解像度ディスプレイに対応させるか、頭を悩ませてきました。SVGはその解決策となり得るでしょう。二倍のサイズのJEPGやPNGを用意して、実寸サイズに縮小する必要はありません。
SVGに対応しているブラウザー
以下のブラウザーでサポートされています。古いブラウザーに対応する機会も減ってきていると思うので、これからどんどん実用化されるのでは?と思います。
- Internet Explorer 9以上
- Firefox 3.0以上
- Chrome 4.0以上
- Mac OS X Safari 3.2以上
- Opera 9.0以上
- iOS Safari 3.2以上
- Androidブラウザ 3.0以上
さよなら、アイコンフォント
アイコンフォントとは、フォントの1文字にテキストではなくアイコンが割り当てられたフォントのこと。こちらもベクター画像として扱える上、IE8以下の古いブラウザーにも対応しているため、高画質ディスプレイに対応させるため多くのデザイナーが採用してきました。Webクリエイターボックスでも過去にアイコンフォントについて「アイコンフォントでリンクタイプ別にアイコンつける方法」という記事内で紹介しています。
しかし欠点があり、アイコンを表示させるためにソースに意味を持たないアルファベットを書かなければならず、万が一フォントファイルがうまく表示されなかった場合、そのアルファベットが表示されてしまいます。またフォントと同じ扱いとなるため、単色しか使えません。新しくアイコンフォントを追加したり、アイコンの修正をする作業は、何かと手間がかかるのも難点でした。
そこで再度注目され始めたのがSVGです。どのように表示していくのか、みてみましょう。
SVGで画像を表示してみよう
画像を表示するには二通りの方法があります。
1. img タグで表示
まずはIllustratorでロゴ画像を用意。保存する際に別名保存を選び、ファイル形式をSVGにすればOK。
<img src="images/logo.svg" alt="ロゴ">
作成されたSVGを img タグで記述します。
See the Pen Logo SVG by Mana (@manabox) on CodePen.
拡大しても劣化しませんね。
2. コードをインラインで記述して表示
他にもHTML文書に直接コードを書き込めます。先ほどと同じようにIllustratorで保存する際に表示されるダイアログで「SVGコード」ボタンをクリックしましょう。ながーいコードが表示されます。これがSVGです。このコードの <svg>〜</svg> をコピーしてHTML文書にペーストすると…
See the Pen SVG inline image by Mana (@manabox) on CodePen.
このように表示されます。意外と簡単ですね!
フィルターを使ってみる
ぼかしや色調の変更等、様々なフィルターが用意されています。例として、ロゴにカーソルをあわせるとぼかしを入れてみましょう。まずは svg にIDを与えます。Illustratorからコードをコピペした場合、デフォルトは「Layer_1」になっていると思うので、わかりやすいIDに変更します。ここでは「logo」というIDに変更しました。次に filter タグを <svg>〜</svg> の中に挿入します。feGaussianBlur はぼかしを、stdDeviation はぼかしの強度を表します。
<svg version="1.1" id="logo" .....>
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="3" />
</filter>
</svg>
続いてCSS。hover すると「pictureFilter」というIDのついたフィルターを実装するよーという意味ですね。ここで使った「pictureFilter」もデフォルト値なので、お好みのIDに変更してもOKです!
#logo:hover {
filter: url(#pictureFilter);
}
See the Pen SVG blur filter by Mana (@manabox) on CodePen.
こんな感じでフィルターがつきました!
See the Pen SVG fractal noise filter by Mana (@manabox) on CodePen.
上記は別のフィルターに変更したところ。カーソルをあわせると歪みます。フィルターは他にもいろんな種類があります。Hands On: SVG Filter Effectsではデモとともにコードが紹介されているので、参考にしてみてください(コードは画像の下に表示されます)。
複数のSVGをコンパクトにまとめて表示
SVGをインラインで表示するにあたり、長いコードがどうもお気に召さない方もいらっしゃるかと思います。私もそうでしたw ひとつ、ふたつならまだしも、多くのアイコンを使いたい場合、もう少しスッキリ表示したいですよね。そこでいろいろ調べたところ、「Icon System with SVG Sprites」という記事で方法が紹介されていました。SVGスプライトと呼ばれているようですね。さっそく試してみたいと思います。
1. 複数のSVGをひとつのファイルにまとめる
まず、長いコードをまとめる外部ファイルを作成します。ここでは「svg-defs.svg」というファイル名にしました。このファイルの中には svg タグ、defs タグ(defines=定義する)、g タグ(group=グループ)を記述します。そのうちの g タグにそれぞれ個別IDを与え、このIDを呼び出すことになります。ひとつの画像の中に多くの g タグが含まれている場合は、一番始めの g タグにIDを付与するとひとつの図形として扱うことができます。
<svg class="defs">
<defs>
<g id="icon1">
<!-- ここにSVGコードが入ります -->
<g>
<g id="icon1">
<!-- ここにSVGコードが入ります -->
<g>
</defs>
</svg>
2. 作成した外部ファイル読み込む
PHPの場合、単純に include_once で読みこめばOK。記述場所は <body> 直下です。ここで読み込まないとChromeでエラーがでるのだとか。
※今回はPHPを使った外部ファイルの読み込み方法を紹介しますが、もちろんHTMLで <body> 直下に 1. でまとめたコードを記述し、必要な箇所で呼び出しても表示されますよ。
<body>
<?php include_once("svg-defs.svg"); ?>
3. SVGを呼び出す
アイコンを表示したい箇所に以下のコードを記述します。use タグでは 1. で与えたIDを記述。svg タグにクラスを付けて、CSSで装飾できるようにします。
<svg viewBox="0 0 100 100" class="icon icon-twitter1"> <use xlink:href="#twitter"></use> </svg>
4. CSSで装飾
2. で読み込んだ外部ファイルはテキストとして表示はされませんが、その部分に空白が挿入されてしまいます。なので、外部ファイルの svg を display: none; で消しちゃいます。
.defs{
display: none;
}
あとはお好みに装飾するだけ。全体を塗りつぶすには color や background-color ではなく、fill を使うことを覚えておきましょう。
.icon {
width: 100px;
height: 100px;
fill: #55acee;
}
See the Pen SVG Sprite by Mana (@manabox) on CodePen.
CSSやフィルター次第で、様々な表現が可能に!
え?なんだかめんどくさい?
ここまでの作業はテンプレート化しておいたり、慣れちゃえば難しくはないのですが、めんどくさそうと感じた方に朗報!IcoMoonというサイトではお好みのアイコンを選択し、画面下の「SVG」というボタンをクリックすればSVGスプライト用のファイルがダウンロードできます!ただ、このサイトで使えるアイコンは限られていますし、オリジナルアイコンを使う場合は、やはり上記のやり方を覚えておくといいかなーと思います。
今回は基本的な扱い方や、便利なSVGスプライトの紹介となりましたが、これにJavaScriptと組み合わせればさらにおもしろい効果を表現できます。今後も少しずつそういった記事を増やしていければと思います!