SVGは画像であると同時に、マークアップ言語でもあります。タグと属性で書いていくSVGのコードはHTMLやCSSとよく似ているので、HTMLやCSSの基礎知識さえあればSVGも同じ考え方で理解できます。今回は、SVGの属性とCSSの書き方を学びます。
見た目の定義は「属性」が基本
SVGの属性の多くは、塗り色、線の色、線の太さといった図形の「見た目」を定義します。文書マークアップ言語であるHTMLでは、文脈に関係のない見た目はCSSで定義することが推奨されています。一方でSVGは、グラフィックのマークアップ言語なので、属性で見た目を定義することは一般的です。
見た目を定義するための主な属性には以下があります。ここでは10の属性をリストアップしていますが、実際にはもっとたくさんの属性があります。
属性名 | 値 | 意味 |
---|---|---|
fill | 色 | 塗り色 |
fill-opacity | 0.0から1.0 | 塗り色の透明度 |
stroke | 色 | 枠線の色 |
stroke-width | 数値 | 枠線の太さ |
stroke-opacity | 0.0から1.0 | 枠線の透明度 |
opacity | 0.0から1.0 | 図形全体の透明度 |
display | inline, none など | 表示、非表示 |
font-family | フォント名 | フォント種 |
font-size | 数値 | 文字サイズ |
font-weight | 太さ | 文字の太さ |
SVGはCSSよりも後に登場した仕様なので(SVG 1.0が2001年リリース、CSS 2が1998年リリース)、いくつかの属性は普段CSSでなじみのあるプロパティとまったく同じ名前になっています。また、それ以外の属性名についても、ハイフン「-
」区切りとなっており、CSSプロパティ名の作法に則っています。SVGの属性名は、当時としてはモダンなルールで決められたわけですね。
それぞれの属性がどのような表示になるのか、簡単に見ていきましょう。
塗り色を指定する「fill属性」
fill属性は、塗り色を指定する属性です。値にはCSSでも使っている「色」を指定します。fill-opacity属性を併用すれば、塗り色の透明度も指定できます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<circle cx="40" cy="40" r="40" fill="#FF4433"></circle>
<circle cx="120" cy="40" r="40" fill="#FF4433" fill-opacity="0.5"></circle>
<circle cx="200" cy="40" r="40" fill="rgb( 33, 150, 234 )"></circle>
<circle cx="280" cy="40" r="40" fill="rgba( 33, 150, 234, 0.5 )"></circle>
</svg>
<body>
塗り色をなしにしたい場合は、値に「none
」を指定します。例ではわかりやすいように枠線(後述)を指定しています。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<circle cx="40" cy="40" r="40" fill="#FF4433" stroke="#000"></circle>
<circle cx="120" cy="40" r="40" fill="none" stroke="#000"></circle>
</svg>
</body>
枠線を指定する「stroke属性」
stroke属性は、枠線を指定する属性です。値には、枠線の色を指定します。デフォルトでは太さ「1
」の枠線が表示されますが、stroke-width属性で変更できます。また、stroke-opacity属性で透明度を指定できます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<circle cx="50" cy="50" r="40" fill="#F43" stroke="#000"></circle>
<circle cx="140" cy="50" r="40" fill="#F43" stroke="#000" stroke-width="10"></circle>
<circle cx="230" cy="50" r="40" fill="#F43" stroke="#000" stroke-width="10" stroke-opacity="0.5"></circle>
</svg>
</body>
stroke-width属性の値にはpx
やem
などの単位は不要です。SVGはあくまでも座標の世界であり、実際に何ピクセルで表示されるかはviewportとviewboxの値によって決まるからです。これは前回解説しましたね。
stroke属性はCSSのborderプロパティに似ていますが、実際の挙動は少し異なります。HTML/CSSのborderは要素の外に描画されるのに対し、SVGのstrokeは要素の縁を中心に内と外の両側に描画されます。
そのほか、枠線には破線や線の先端の見た目などのオプションを指定できます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<polyline points="10, 20, 290, 20" stroke="#000" stroke-width="10"></polyline>
<polyline points="10, 60, 290, 60" stroke="#000" stroke-width="10" stroke-dasharray="20 30"></polyline>
<polyline points="10, 100, 290, 100" stroke="#000" stroke-width="10" stroke-linecap="round"></polyline>
</svg>
</body>
表示/非表示を指定する「display属性」
display属性では、図形の表示/非表示を指定できます。図形を非表示にしたい場合は、diplay属性の値に「none
」を指定します。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<circle cx="40" cy="40" r="40" fill="#FF4433"></circle>
<circle cx="120" cy="40" r="40" fill="#FF4433" display="none"></circle>
<circle cx="200" cy="40" r="40" fill="#FF4433" display="inline"></circle>
<circle cx="280" cy="40" r="40" fill="#FF4433" display="table"></circle>
</svg>
</body>
none
以外に、「inline
」「block
」「table
」といった、CSSのdiplayプロパティとまったく同じ値も受け付けますが、どの値を指定しても図形は表示されるだけで、レイアウトには影響がありません。
なお、Adobe Illustratorでレイヤーを非表示にしてSVGファイルに書き出すと、該当図形に「display="none"」
が指定された状態のソースコードとなります。
テキストの見た目を制御する「font-◯◯」属性
SVGではtext要素でテキストも扱えます。テキストの見た目は、CSSでおなじみの「font-family
」「font-size
」「font-weight
」などの属性で変更できます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<text x="10" y="40">本気で使いこなす「SVG」再入門</text>
<text x="10" y="80" font-size="20">本気で使いこなす「SVG」再入門</text>
<text x="10" y="120" font-size="20" font-family="'Noto Sans Japanese', sans-serif">本気で使いこなす「SVG」再入門</text>
<text x="10" y="160" font-size="20" font-family="'Noto Sans Japanese', sans-serif" font-weight="bold">本気で使いこなす「SVG」再入門</text>
</svg>
</body>
ただし、テキストの色指定はHTML/CSSと異なり、colorではなく、fill属性を利用します。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<text x="10" y="40">本気で使いこなす「SVG」再入門</text>
<text x="10" y="80" fill="#FF4433">本気で使いこなす「SVG」再入門</text>
</svg>
</body>
座標を調整する「transform属性」
transfrom属性は、図形の座標を調整する属性です。Illustratorなどで書き出したSVGファイルにはtransform属性が含まれていることがあり、コードを冗長にしてしまう邪魔な存在に見えるかもしれません。しかし、SVGを活用して複雑なWebアプリケーションを作るときには、知っておくと便利な属性です。
transform属性の使い方は、CSS3の「2D Transforms」とほとんど同じです。というのも、2D Transformsは、SVGのtransform属性をもとにして作られています。
transfrom属性の値には、以下の関数を指定できます。このうち、「translate」と「rotate」の2つを覚えておけば十分です。
機能 | 関数 |
---|---|
x, y 方向の移動 | translate(<移動量>[, <移動量>]) |
x方向の移動 | translateX(<移動量>) |
y方向の移動 | translateY(<移動量>) |
x, y方向の伸縮 | scale(<数値>[, <数値>]) |
x方向の伸縮 | scaleX(<数値>) |
y方向の伸縮 | scaleY(<数値>) |
回転 | rotate(<角度>) |
x方向のせん断 | skewX(<角度>) |
y方向のせん断 | skewY(<角度>) |
行列指定 | matrix(<数値>, <数値>, <数値>, <数値>, <数値>, <数値>) |
例えば図形の位置を移動したい場合は、次のように値にtranslate関数を利用します。元の位置(黒の半透明の四角)から、右に20、下に50移動していることが確認できます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<rect x="50" y="50" width="80" height="80" opacity="0.5"></rect>
<rect x="50" y="50" width="80" height="80" transform="translate( 20, 50 )"></rect>
</svg>
</body>
図形を回転させたい場合は、値にrotate関数を利用し、引数に角度を指定します。回転軸の座標を第2、第3引数に指定できます。次のコードでは、座標( x:90, y:90 )を中心に、45度回転させています。第2、第3引数を省略すると、原点( x:0, y:0 )を軸に回転します。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<rect x="50" y="50" width="80" height="80" opacity="0.5"></rect>
<rect x="50" y="50" width="80" height="80" transform="rotate( 45, 90, 90 )"></rect>
</svg>
</body>
transfrom属性には、スペース区切りで複数の値を指定できます。例えば次のコードでは、図形を移動させた後に回転させています。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<rect x="50" y="50" width="80" height="80" opacity="0.5"></rect>
<rect x="50" y="50" width="80" height="80" transform="translate( 20, 50 ) rotate( 45, 90, 90 )"></rect>
</svg>
</body>
このように、transform属性を利用すると、図形を簡単に動かすことができます。スライダーUIのハンドル部分のように、頻繁に移動させたい図形の位置はtransformで管理すると便利です。
以下の例では、原点に配置したやや複雑な図形をtransform属性で動かしています。path要素のように複雑な図形であっても、意図した位置に簡単に配置できることがわかりますね。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<path transform="translate(100,100)" fill="#4CAF50" d="M-22.2,14.1c0,0-9.6-17,30-28C30.3-20.2,29.8-30,29.8-30s4.6,44.1-34.1,48.3c0,0-10.5,1.8-16-1.1c0,0-5.5,8.5-4.7,12.6L-30,30c0,0,8.5-16.9,12.4-18.9L-22.2,14.1L-22.2,14.1z"/>
</svg>
</path>
一括して属性を指定する「g要素」
複数の図形(要素)の見た目を一括して指定したい場合もあるでしょう。そうした場合はg要素を利用します。g要素のgはgroup(グループ)の頭文字で、HTMLでいうdiv要素に近い存在です。
g要素で図形をグループ化し、g要素に対して属性を指定すれば、g要素に含まれる子孫要素へ属性が引き継がれます。
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<g fill="#FF4433" stroke="#BB1111" stroke-width="10">
<circle cx="50" cy="50" r="40"></circle>
<circle cx="140" cy="50" r="40"></circle>
</g>
<circle cx="230" cy="50" r="40"></circle>
</svg>
</body>
SVGのCSSを利用する
SVGはグラフィックスのマークアップ言語なので、属性で見た目を定義します。しかし、場合によってはCSSを利用すると管理しやすかったり、あるいはCSSを利用しないと実現できない表現もあったりします。
例えば、図形の形状は同じでテーマカラーだけを変更する、といった場合はSVGのCSSが便利です。
次の例では、class属性に応じて図形の色などが変わっていることを確認できます。SVGでもHTMLと同じように、class属性を使ってCSSを適用します。SVG内にCSSのコードを書くには、HTMLとよく似た、SVGのstyle要素を利用します。defs要素はHTMLのhead要素と似た役割で、表示しないメタ情報を配置するための要素です。
(解説用に図形のd属性を一部省略しています)
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<defs>
<style>
.char1 .body,
.char1 .leg,
.char1 .arm { fill: #82B1FF; }
.char1 .face { fill: #2962FF; }
.char2 .body,
.char2 .leg,
.char2 .arm { fill: #FF8A80; }
.char2 .face { fill: #D50000; }
</style>
</defs>
<g class="char1" transform="translate( 64, 64 )">
<path class="leg" d="M17.2,45.9(省略)"/>
<path class="arm" d="M-32.7,24.1(省略)"/>
<path class="body" d="M-22.8-16.3(省略)"/>
<path class="face" d="M-13.7-8.3(省略)"/>
</g>
<g class="char2" transform="translate( 128, 64 )">
<path class="leg" d="M17.2,45.9(省略)"/>
<path class="arm" d="M-32.7,24.1(省略)"/>
<path class="body" d="M-22.8-16.3(省略)"/>
<path class="face" d="M-13.7-8.3(省略)"/>
</g>
</svg>
</body>
SVG用のCSSのプロパティ名と値は、SVGの属性の名前と値と一致します。ですので、SVGの属性を覚えておけば、迷うことなくCSSも書けます。
親ドキュメントとなるHTML側に適用されているCSSをSVGに適用することもできます。次の例は、HTMLのstyle要素がSVG側にも影響を与えていることがわかります。HTMLのlink要素を利用して読み込んだ外部CSSファイルについても同様です。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>=^.^=</title>
<style>
body{ background: url( 'bg.png' ); }
.char3 .body,
.char3 .leg,
.char3 .arm { fill: #00BFA5; }
.char3 .face { fill: #009688; }
</style>
</head>
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<g class="char3" transform="translate( 64, 64 )">
<path class="leg" d="M17.2,45.9(省略)"/>
<path class="arm" d="M-32.7,24.1(省略)"/>
<path class="body" d="M-22.8-16.3(省略)"/>
<path class="face" d="M-13.7-8.3(省略)"/>
</g>
</svg>
</body>
</html>
:hover擬似クラスでマウスオーバーを実現する
マウスオーバー効果は、CSSを利用すると簡単に実現できます。SVGの要素にもCSSの:hover擬似クラスは有効ですので、CSSの仕組みを使ってHTMLと同様のマウスオーバー効果を簡単に導入できます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>=^.^=</title>
<style>
body{ background: url( 'bg.png' ); }
.char3 .body,
.char3 .leg,
.char3 .arm { fill: #00BFA5;
transition: fill 0.5s; }
.char3 .face { fill: #009688;
transition: fill 0.5s; }
.char3:hover .body,
.char3:hover .leg,
.char3:hover .arm { fill: #FF80AB; }
.char3:hover .face { fill: #C51162; }
</style>
</head>
<body>
<svg width="320" height="200" viewBox="0 0 320 200">
<g class="char3" transform="translate( 64, 64 )">
<path class="leg" d="M17.2,45.9(省略)"/>
<path class="arm" d="M-32.7,24.1(省略)"/>
<path class="body" d="M-22.8-16.3(省略)"/>
<path class="face" d="M-13.7-8.3(省略)"/>
</g>
</svg>
</body>
</html>
ブラウザーがCSS3のtransitionに対応していれば、これも合わせて機能します。
メディアクエリーも使える
SVGのCSSでもmedia規則は有効です。media規則の中でも特によく使われているメディアクエリーも、もちろんSVG上で機能します。
次の例では、ブラウザーのウィンドウサイズに応じて、シンプルな図形を表示するか否かを切り替えています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>=^.^=</title>
<style>
body{ background: url( 'bg.png' ); }
@media ( max-width: 640px ) {
.default{ display: none; }
}
@media ( min-width: 640px ) {
.simple{ display: none; }
}
</style>
</head>
<body>
<svg width="128" height="128" viewBox="0 0 128 128">
<g class="default">
<path (省略) />
</g>
<g class="simple">
<path (省略) />
</g>
</svg>
</body>
</html>
なお、インラインSVGではなく、HTMLのimg要素などで画像ファイルとして読み込んだSVGでは、メディアクエリーの挙動は異なります。画像としてSVGファイルを読み込んむと、画像のサイズがビューポートの大きさとなり、その大きさに応じてメディアクエリーが適用されます。
次の例は、HTMLでは、同じSVGファイルをimg要素で読み込み、異なるサイズで表示しています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>=^.^=</title>
<style>
body{ background: url( 'bg.png' ); }
</style>
</head>
<body>
<img src="17.svg" alt="" width="128" height="128">
<img src="17.svg" alt="" width="64" height="64">
</body>
</html>
読み込んでいるSVGファイルでは、横128pxを境にしたメディアクエリーが書かれています。1つ目のimg要素ではSVGファイルを128pxで読み込んでいるので、128px以上のメディアクエリーが適用されます。2つ目のimg要素では64pxに指定しているので、127px以下のメディアクエリーが有効となっています。
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
<defs>
<style>
@media ( max-width: 127px ) {
.default{ display: none; }
}
@media ( min-width: 128px ) {
.simple{ display: none; }
}
</style>
</defs>
<g class="default">
<path (省略) />
</g>
<g class="simple">
<path (省略) />
</g>
</svg>
まとめ
SVGにはさまざまな属性が用意されており、これらを組み合わせれば、HTMLとはひと味違う表現ができることがわかりました。とはいっても、使い方はHTMLとほとんど同じです。また、SVGのCSSについても、HTMLのCSSの書き方を知っていれば難しくないでしょう。HTML5の登場でSVGとHTMLの関係は以前よりも近くなっています。SVGを導入して、HTMLの表現の世界を広げましょう。