仕様から考えるSVGファイル最適化について
Adobe Illustrator CC 2015.3で「別名で保存」からSVGファイルを書き出すとこのようになります。
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 210 210" enable-background="new 0 0 210 210" xml:space="preserve"> <rect fill="#42479B" width="210" height="210"/> <polygon fill="#FFA500" points="106.2,12.5 135.7,72.2 201.6,81.8 153.9,128.3 165.2,194 106.2,163 47.2,194 58.5,128.3 10.8,81.8 76.7,72.2 "/> </svg>
このままだと不要な記述や省略できる部分が多くあります。
例えば最適化ツールのSVGOを適用すると、
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210"> <path fill="#42479B" d="M0 0h210v210H0z"/> <path fill="#FFA500" d="M106.2 12.5l29.5 59.7 65.9 9.6-47.7 46.5 11.3 65.7-59-31-59 31 11.3-65.7-47.7-46.5 65.9-9.6z"/> </svg>
(※見やすいようにここでは改行とインデントを追加)
かなりすっきりしました。
このように、オーサリングツールから出力されたSVGファイルには省略できる記述が多く、SVGOやScourなどを用いてそれらを削ることでファイルサイズの軽量化を行えます。
しかし一方でツール任せにしてしまうと、どういった根拠があってその記述を削除しているのか?最適化による弊害は無いのか?といった点は気がかりではあります。
そこでこの記事ではSVGの様々な要素について解説していき、なぜ削除できるのか?仕様の面での裏付けや、またその場合の注意点などを挙げていきます。
簡易目次
はじめに
SVGはXMLを基盤にした2次元グラフィックス記述言語です。
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 210 210" enable-background="new 0 0 210 210" xml:space="preserve"> <rect fill="#42479B" width="210" height="210"/> <polygon fill="#FFA500" points="106.2,12.5 135.7,72.2 201.6,81.8 153.9,128.3 165.2,194 106.2,163 47.2,194 58.5,128.3 10.8,81.8 76.7,72.2 "/> </svg>
それを踏まえてIllustratorから出力されたSVGファイルを見ると2つの部分に分けられます。
- XML宣言
- ルート要素
ここではこの基本構造と各属性などについて解説していきます。SVGには他にもrect要素やpath要素などの図形に関する要素もありますが、今回はそれらは扱いません。
また特に記載の無い場合、基になる仕様はSVG 1.1 Second Editionとしますが、次期バージョンとして現在策定中のSVG 2ではどのように変わり、将来的にはどうなる予定なのか?といった補足を行う項目もあります。
XML宣言
SVG文書はXML文書でもあるので、始めにXML宣言を記述することが推奨されます。
<?xml version="1.0" encoding="utf-8"?>
ですが、XML宣言はこれらの条件を満たしていれば省略が可能です。
- XMLのversionが
1.0
である - スタンドアロン文書宣言が
no
である - 文字コードがUTF-8またはUTF-16である、もしくはContent-Typeヘッダなどに文字コードの情報がある
一つ目のversionはそのまま1.0
ですから問題ありません。
スタンドアロン文書宣言はyes
またはno
の値を持ち、仮にyes
であればこのように記述されます。
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
しかし、Illustratorから出力されたSVGファイルにはそもそも記述自体がありません、このようにスタンドアロン文書宣言を省略した場合はno
と見なされます。
そのため二つ目の条件も満たしています。
続いて文字コードについて。
Illustratorの初期設定では文字コード設定はUTF-8であるため、特に変更していない限りは条件を満たします。またレスポンスヘッダのContent-TypeでこのようにMIMEタイプと一緒に文字コードを提示できます。
コメント
<!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
XMLはHTMLと同じく<!--
と-->
で囲んだ部分がコメントとなります。
Illustrator以外の他のオーサリングツールでものソフトウェア・アプリの名前やバージョンなどをコメントで記述して出力することが多いです。しかし、利用者にとってはこうした情報が直接なにかの役に立つわけではありませんから、削除してファイルサイズを軽量化した方が良いでしょう。
文書型宣言
最新版のAdobe Illustratorでは記述しなくなりましたが、Illustrator CC以前では文書型宣言をSVGファイルに記載していました。今回はせっかくなので、こちらも解説します。
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
文書型宣言はSVG 1.1 SEでは非推奨になっており削除するのが望ましいです。
この仕様では DTD が与えられているが、 XML 文書の妥当性検証には問題がある事も知られている。 特に、 DTD では名前空間をスマートに扱えない。 SVG 文書に DOCTYPE 宣言を含める事は、推奨されない。
古いSVGファイルなどで文書型宣言が記述されたものがあれば削除しておいた方が良いでしょう。
ルート要素
続いてルート要素である、最も外側のSVG要素の各属性について解説していきます。
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 210 210" enable-background="new 0 0 210 210" xml:space="preserve">
SVG名前空間宣言
<svg xmlns="http://www.w3.org/2000/svg">
SVG名前空間宣言はSVGファイルには必ず記述しなければなりません。
いかなる場合でも、すべての SVG 要素が SVG 名前空間に属するものと識別されるようにするためには, XML 名前空間 勧告 [XML-NS] に従って SVG 名前空間宣言が与えられなければならない。
古いSVGファイルでは名前空間宣言が無いことも
SVG 1.0の仕様がW3Cから勧告されたのは2001年9月、実は勧告案の段階ではSVG名前空間宣言の省略が可能でした。そのため勧告前の2000年6月にリリースされたIE用プラグインのAdobe SVG Viewerでは、名前空間宣言が無くてもSVGを表示できました。
そのこともあってか、当時のAdobeのページではSVG名前空間宣言の無いSVG文書がサンプルとして掲載されています。古いSVGの書籍や、当時のウェブサイトではこうしたSVG名前空間宣言の無いSVG文書の作例が残っていることもありますが、現在の仕様では適切に表示できないので留意してください。
HTML5のSVG要素では名前空間宣言が省略できる
なお、SVGファイルではなくHTML5のSVG要素として扱う場合にはSVG名前空間宣言は省略できます。
XLink名前空間宣言
HTMLではリンクを張る際には
<a href="http://example.com/">リンクテキスト</a>
a要素にhref
属性で記述します。
一方でSVG文書ではXLink名前空間のhref
属性を使います。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a xlink:href="http://example.com/"> <path fill="#42479B" d="M0 0h210v210H0z"/> </a> </svg>
Illustratorから出力されるSVGファイルも含め、多くの場合はXLink名前空間と共に接頭辞が宣言されxlink:href
属性として使われます。
xlink:href
属性はa要素やimage要素、use要素など様々な要素で使われ、それらの要素でリンク機能を利用するのであればXLink名前空間宣言は必ずしなければなりません。
ただし、a要素やimage要素、use要素などのリンクを行う要素がSVG文書に含まれないのであれば、XLink名前空間宣言は省略できます。具体的には冒頭の例ではpath要素のみであるため、XLink名前空間宣言が省かれています。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210"> <path fill="#42479B" d="M0 0h210v210H0z"/> <path fill="#FFA500" d="M106.2 12.5l29.5 59.7 65.9 9.6-47.7 46.5 11.3 65.7-59-31-59 31 11.3-65.7-47.7-46.5 65.9-9.6z"/> </svg>
SVG 2ではXLink名前空間宣言が省略できる予定
現在策定中のSVG 2ではXLink名前空間宣言及び接頭辞は省略できるようになる予定です。
xlink:href 属性は、名前空間なしの href の利用の支持を受けて,廃止予定にされた。
つまり従来のSVG 1.1 SEの仕様ではこのように
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 210 210"> <defs> <path id="star" fill="#FFA500" d="M106.2 12.5l29.5 59.7 65.9 9.6-47.7 46.5 11.3 65.7-59-31-59 31 11.3-65.7-47.7-46.5 65.9-9.6z"/> </defs> <use xlink:href="#star"/> </svg>
use要素などでは、XLink名前空間宣言を行いxlink:href
属性を使う必要がありました。
しかし、SVG 2では
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210"> <defs> <path id="star" fill="#FFA500" d="M106.2 12.5l29.5 59.7 65.9 9.6-47.7 46.5 11.3 65.7-59-31-59 31 11.3-65.7-47.7-46.5 65.9-9.6z"/> </defs> <use href="#star"/> </svg>
このようにXLink名前空間宣言をせずともhref
属性だけで済むようになる予定です。
ただ将来的な話はさておき、href
属性の現在の実装状況はどうか?というと芳しくありません。
SVG 2のhref
属性の対応状況
xlink:href 属性 | href 属性 |
---|---|
対応している環境
- IE11(IE10以下は未検証)
- MS Edge
- Chrome / Opera
未対応な環境
- Firefox
- Safari
またAdobe Illustrator、Inkscapeといったオーサリングツールでも未対応です。そもそも策定途中の仕様であるため仕方ないのですが、現段階ではXLink名前空間宣言の省略は行わない方が良いでしょう。
viewBox
属性
冒頭で挙げたSVGOでの最適化の例でもある通り、
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210"> <path fill="#42479B" d="M0 0h210v210H0z"/> <path fill="#FFA500" d="M106.2 12.5l29.5 59.7 65.9 9.6-47.7 46.5 11.3 65.7-59-31-59 31 11.3-65.7-47.7-46.5 65.9-9.6z"/> </svg>
viewBox
属性が残っていることからSVG文書には必須の属性であると誤解されがちですが仕様上は省略が可能です。
ただし、viewBox
属性を省略した場合は挙動が複雑になりがちで、扱いが難しくSVG上級者向けの手法です。特に理由がない限りは原則viewBox
属性を記述した方が使いやすいです。
version
属性
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
Illustratorでの初期設定ではversion
属性はSVG 1.1 SEを示す1.1
で書き出されます。
策定中のSVG 2では削除が予定されています。
svg 要素から baseProfile, version 属性が削除された。
x
属性、y
属性
<svg x="0px" y="0px" xmlns="http://www.w3.org/2000/svg">
x
属性、y
属性は記述が無い場合はそれぞれ0
と見なされるので、こうした場合には省略が可能です。そしてさらに言えば
( 最も外側の svg 要素 に対しては、どんな意味も効果も生じない。)
と定義されており、ルート要素(最も外側のsvg要素)では仮にx="0"
でもx="300"
であっても記述する意味が無いので省略した方が良いでしょう。
enable-background
属性
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 210" enable-background="new 0 0 210 210">
enable-background
属性については詳しくは別の記事でまとめています。
enable-background属性の意味と省略できる理由について
内容を一行で簡潔にまとめると
enable-background
属性が実装された環境は現状ほぼ無く、記述してもしなくても同じなので省略すべき
となります。
xml:space
属性
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
xml:space
属性は省略によって挙動を変えるため、記述に手を加えるべきかは状況によります。
xml:space
属性はdefault
(初期/既定値)とpreserve
の2種類の値をとり、文字列における空白の処理を指定します。それぞれの指定の共通する部分、また違う部分をまとめると
default
とpreserve
どちらも共通の扱い
- 全てのタブ文字をスペース文字に置き換える。
default
での扱い
- 全ての改行を取り除く
- 先頭及び、末尾の連続するスペース文字を取り去る
- 連続するスペース文字は1個にまとめられる
preserve
での扱い
- 全ての改行はスペース文字に置き換えられる
となります。
xml:space
属性でdefault
とpreserve
の比較
具体的にはこのような指定にした場合
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 60"> <text xml:space="default" y="20"> Scalable Vector Graphics </text> <text xml:space="preserve" y="40"> Scalable Vector Graphics </text> </svg>
文章の表示にこうした違いが現れます。
SVGの仕様において、xml:space
属性の影響が現れるのは概ねtext要素です。
その場合に安易にxml:space
属性を削除してしまった場合には規定値であるdefault
と見なされ、意図とは違うずれが生じる可能性があります。SVGOには珍しく、最適化によって挙動が変わる処理なので該当する要素がある際には注意が必要です。
ただ、そもそも文字の配置にスペース文字やタブ文字、改行で調整するのは避けるべきですが……。