画面右下のトップに戻るボタンを例に,SVGをCSSで指定する方法の自分用備忘録.
何の経験も知識もないド素人が,このブログを少しでも良くしたいとの思いだけで,その都度必要なことを調べたり自分で手を動かしたりした内容を忘れないように書いているだけです.
ちゃんと技術書を読んで仕様の勉強をしたわけではないので間違った表現やワケわかってないところが多々あります.
コピペは自由ですが,ちゃんとこういうの↓も参考にして,自己責任でお願いします・・・
間違った表現等気になる部分がありましたら,お問合せからこっそり(笑)教えてもらえると勉強になります.
CSSか?SVGか?fontawesomeか?
トップに戻るボタンみたいな単純な図形であれば,CSSでそのまま書いてしまうこともできるけど,中を切り抜いたような表現をCSSだとどうしたらいいのか(そもそもできるのかどうかすら)わからない.
こうじゃなくて
こうしたい
ってこと.
全体的に透けてるんじゃなくて,中は切り抜きたい.
俺の微妙なこだわり(笑)
だからCSSではなくSVGにした.
あと,CSSでそのまま描いた方がSVGよりファイルサイズが小さくなるのかというと,それは一概にそうとも言えない.
単純なSVGファイルは記述も短くて軽いから,場合によってはCSSより軽くなることもあった.
だったら,くり抜いたり複雑にしたりとinkscapeで自由にデザインできるSVGに統一した方が管理もしやすくていいかなと思っているけど,まあ場合によってはCSSでデザインするのもありかもとも思ったり.
今のところは全部SVGを使っている.←追記:スマホ画面左上のハンバーガーメニューはCSSに変えた.
fontawesomeは読み込みに負荷がかかるので,バージョンアップしたタイミングで使っているアイコンを全部SVG化して導入をやめた.
数えるほどしかアイコン使っていないのに,無数のアイコンをわざわざ読み込む必要なし.
SVGイメージのURLについて
CSSで指定する場合はURL(ここにSVGイメージのURL);
という形で記述するけど,このURLにもいくつか記述方法がある.
外部ファイルURLの場合
そのままURLを書き込めばOK.
例:
URL("https://orery-blog.github.io/files/svg/chevron-circle-up.svg");
dataURLの場合
今のところ俺はこの方法で統一するつもり.
直接書き込んだ方が読み込みに行かないぶん動作が軽くなるから.
書き方としては,
url("data:image/svg+xml,SVGファイルの中身");
こんな感じ.
ポイントは2つ.
このSVGファイルの中身だけど,本当にそのままそっくりタグ付きのまま書き込んで,エンコードも何もしなくてもプレビュー表示はできたりする.
でも,アップロードしたら表示されてなかった.
あと,プレビュー表示でも,色指定のfill
を追加したら#
があると表示されなかった.
色の名前で書き込めば#
使わないからちゃんとその色で表示された.
例:#fff(エンコード後は%23fff) → white(エンコード後もwhite)
SVGの中身は画像と違ってバイナリデータではなくてxmlで書かれているから,プレビュー表示ではうまく行くのかな?わかんない.
URLエンコードをしておくと無難だと思うのでしておく.
エンコードしない方がサイズは小さいけどね.
#
は3倍の%23
になるし.
URL全体を囲んでるやつと,URLの中で囲んでるやつは同じだとうまくいかない.
どういうことかというと,content:url(" 中身 ");
の場合,中身の中に「"
」があるとうまくいかない.
うまくいかない例:
url("data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"%3E%3Cpath d="M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z"/%3E%3C/svg%3E");
うまくいく例(パターン1):
url("data:image/svg+xml,%3Csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"%3E%3Cpath d=\"M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z\"/%3E%3C/svg%3E");
うまくいく例(パターン2):
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
つまり,クォート内でクォートを利用するときは,エスケープするか,もしくは違うクォートを使えば問題ない.
- シングルクォート(')内のシングルクォート(')はエスケープ(\')する
- ダブルクォート(")内のダブルクォート(")はエスケープ(\")する
- シングルクォート(')内はダブルクォート(")にする
- ダブルクォート(")内はシングルクォート(')にする
※¥と\が混在しているかもしれませんが,同じものです.
前置き長かったな.
ということで以下実際にCSSに書く方法.
これ以降出てくるCSSの使用例は全て,見た目はまったく同じ表示になる.
つまりhtmlで<div class="page_top"/>
と書くと,画面右下にトップに戻るボタンが表示される.
contentを使う
content
でSVGイメージを指定しても,background-image
でSVGイメージを指定しても,挙動がほとんど同じだった.
違いがあったとすれば,サイズ指定の仕方によっては,background-image
で指定した場合はSVGイメージの繰り返しが起きた.
content
で指定した場合は繰り返しは起きない.
そもそもSVGアイコンを使いたいときって繰り返して使いたい事なんてないだろうからcontent
使えばいいかなと思うけど,background-image
の繰り返しはbackground-repeat:no-repeat
で消せるから,汎用性や意味合い的なことを考えれば,background-image
を使う方が自然な気はしている.
直接contentに指定する場合
- CSS短い
- 疑似要素の空きがある
- 色を変えられない
- htmlで記述したものが表示されない
htmlで記述したものが表示されないって言うのは,例えば,
<div class="page_top">hoge</div>
と記述したとして,page_topクラスを付与したタグで囲んだhoge
は表示されない.
※hoge
が表示されるようにするには後述する疑似要素を使う.
なお,色は変えられないけど,opacity
は効く.
色を変える場合は,SVGのURLの中に直接色を指定するコードを入れるか,後述するmask-image
で指定する.
使用例:
.page_top{
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%233fefee' opacity='.6' d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
}
この例のパターンではopacity
はSVGの中身(path)で指定したけど,position
とかと並べて指定しても効く.
疑似要素で指定する場合
- CSS短い
- htmlで記述したものが表示できる
- 色を変えられない
- サイズが変えられないことがある?
SVGではなく画像ファイルだと,外部URLの場合は疑似要素の時はサイズの指定が効かなくなった.
background-image
でも画像の場合はなんかサイズ指定うまくできない.
でもSVGは外部URLでもサイズ指定できそう.
よくわからない.
まあ外部URLも画像も使わないからいいや.
使用例:
.page_top::before{
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%233fefee' opacity='.6' d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
}
background-imageを使う
content
を使った時とほとんど同じ.しいて言うなら
直接background-imageに指定する場合
さっきcontent
って書いてたところをそっくりそのままbackground-image
に変えるだけ.
使用例:
.page_top{
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%233fefee' opacity='.6' d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
}
疑似要素を使う場合
content:'';
を追加するのを忘れない.
使用例:
.page_top::before{
content:'';
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%233fefee' opacity='.6' d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
}
mask-imageを使う
すごい便利がいいしオールマイティに使えそうだから,以前は全部この書き方にしてた.
content
でもbackground-image
でもひっかかってた画像のサイズとかもちゃんと指定できるし.
でも,mask-image
はベンダープレフィックス(-webkit
とか接頭辞がつくやつ)が必要なせいで無駄に複数回SVGのデータを書き込むことになってメンテナンス性が悪いし,俺別に外部URL使ってないし,場所によって色を変えたい時っていうのが今のところないので結局今はこの方法はあんまり使ってない.
なおこれもbackground-image
同様SVGイメージの繰り返しが起きる.
- background-colorで色を変えられる
- 外部URLでも色が変えられる
- ベンダープレフィックスつけるとCSSが極端に長くなる
どれだけ長くなるかわかりやすいように右端で折り返してみた↓
使用例:
.page_top{
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
background-color: rgba(63, 239, 238,.6);
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E")
}
今は-webkit
をひとつプラスするだけで良さそうだけど,少し前までは-o
とか-ms
とかもっとたくさん記述しないといけなかったから,まあマシにはなったけど.
background-color
で色指定できるのは便利(SVGの中身いちいち書き換えなくていい)だから,mask-image
が完全に標準化したらまた戻すかも.
疑似要素の場合
background-image
の時と同じく,content:'';
を忘れない.
使用例:
.page_top::before {
content: '';
position: fixed;
width: 50px;
height: 50px;
right: 0;
bottom: 0;
background-color: rgba(63, 239, 238,.6);
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E");
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z'/%3E%3C/svg%3E")
}
まとめ
簡単にまとめ.- dataURLの場合はSVGをURLエンコードする
- →クォート内では同じクォートを使わない
- SVGのpathに直接色を記述してcontentかbackground-imageでURL指定する
- →色を自由に変えたいときはmask-imageを使う
ちなみに現時点ではこのトップに戻るボタンは,CSSで指定せずにhtmlに書いてます.
(今日この記事で使いまわすことになったから・・・笑)
このデザインでしかこのアイコンは使わないって場合にはCSSで指定しちゃうのがhtml書くのも簡単で楽な気がしています.
今回で言えば,htmlに<div class="page_top"/>
って書くだけですから.