1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

svgのCSS埋め込み私的メモ 何をエンコードすれば良い?

Last updated at Posted at 2022-05-25

はじめに

何の文字をエンコードすればいいのか調査してみた

正しくsvgの何の文字をエンコードすればいいのか、ぐぐっても、どくっても、出てこないのもありました。

前提

以下のようなperlコードにおいて外部ファイル化したSVGを自動で埋め込むこととする

svgfont.pl
print <<EOM;
.icon-twitter-white {
	background: url('@{[&svg("icon-twitter.svg","#000","#fff")]}') no-repeat center;
}

.icon-twitter-black {
	background: url('@{[&svg("icon-twitter.svg","#000","#000")]}') no-repeat center;
}

EOM

なお、今回使用するSVGアイコンは以下となります

icon-twitter.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 48 48"><path fill="#000" d="M34.87 7.86v1c0 10.53-8 22.67-22.67 22.67A22.49 22.49 0 0 1 0 28a15 15 0 0 0 1.9.12 16 16 0 0 0 9.89-3.42 8 8 0 0 1-7.44-5.54A8 8 0 0 0 8 19a8 8 0 0 1-6.4-7.81v-.11a7.93 7.93 0 0 0 3.62 1A8 8 0 0 1 2.7 1.45a22.63 22.63 0 0 0 16.43 8.33 8 8 0 0 1 13.58-7.27A16 16 0 0 0 37.77.58 8 8 0 0 1 34.26 5a15.82 15.82 0 0 0 4.58-1.26 16.24 16.24 0 0 1-3.97 4.12Z"/></svg>

最初は

開発時、base64なら確実であったのもあるので、めんどくさいので base64でエンコードを行っていました

svgfont.pl
sub svg {
	my($svg,$before,$after)=@_;
	my $ret=`cat $svgsrc/$svg|sed -e 's/$before/$after/g'| base64 | sed -z 's/\\n//g'`;
	return "data:image/svg+xml;base64," . $ret;
}

実質上のUS-ASCIIで埋め込む

CSSに埋め込むにあたってここが苦労しました。
base64であればすべての文字が肥大化しますので格段に容量が増えますが
US-ASCIIで埋め込めば最小限の文字列ですみます。

svgfont.pl
sub svg {
	my($svg,$before,$after)=@_;
	my $ret=`cat $svgsrc/$svg|sed -e "s/'/\\\'/g" | sed -e 's/"/\\\"/g' |sed -e 's/ /%20/g'| sed -e 's/$before/$after/g'| sed -e 's/#/%23/g'|sed -z 's/\\n//g'`;
	return "data:image/svg+xml," . $ret;
}

$before、$after はただの色置換です。
置換する必要がなければ、同じ値をいれておきます

また、そう大して負荷がかかるわけではないが、base64をデコードするより、%をデコードするほうのが、CPU的には優しいのかもしれません

URLに記載される :// もエンコードしている例もありますが
エンコードする必要がありませんでした。

# の文字はエンコードしないと使い物にならないのは知っていましたが
以外と「 」(半角スペース)をエンコードしないとだめだったわけです

また、マルチバイト文字が入るわけではないことを前提としていますので、;utf8 の記載は節約しています

生成されたCSS

icon-twiter.css
.icon-twitter-white {
	background:url('data:image/svg+xml,<svg%20xmlns="http://www.w3.org/2000/svg"%20version="1.1"%20viewBox="0%200%2048%2048"><path%20fill="%23fff"%20d="M34.87%207.86v1c0%2010.53-8%2022.67-22.67%2022.67A22.49%2022.49%200%200%201%200%2028a15%2015%200%200%200%201.9.12%2016%2016%200%200%200%209.89-3.42%208%208%200%200%201-7.44-5.54A8%208%200%200%200%208%2019a8%208%200%200%201-6.4-7.81v-.11a7.93%207.93%200%200%200%203.62%201A8%208%200%200%201%202.7%201.45a22.63%2022.63%200%200%200%2016.43%208.33%208%208%200%200%201%2013.58-7.27A16%2016%200%200%200%2037.77.58%208%208%200%200%201%2034.26%205a15.82%2015.82%200%200%200%204.58-1.26%2016.24%2016.24%200%200%201-3.97%204.12Z"/></svg>') no-repeat center;
}

.icon-twitter-black {
	background:url('data:image/svg+xml,<svg%20xmlns="http://www.w3.org/2000/svg"%20version="1.1"%20viewBox="0%200%2048%2048"><path%20fill="%23000"%20d="M34.87%207.86v1c0%2010.53-8%2022.67-22.67%2022.67A22.49%2022.49%200%200%201%200%2028a15%2015%200%200%200%201.9.12%2016%2016%200%200%200%209.89-3.42%208%208%200%200%201-7.44-5.54A8%208%200%200%200%208%2019a8%208%200%200%201-6.4-7.81v-.11a7.93%207.93%200%200%200%203.62%201A8%208%200%200%201%202.7%201.45a22.63%2022.63%200%200%200%2016.43%208.33%208%208%200%200%201%2013.58-7.27A16%2016%200%200%200%2037.77.58%208%208%200%200%201%2034.26%205a15.82%2015.82%200%200%200%204.58-1.26%2016.24%2016.24%200%200%201-3.97%204.12Z"/></svg>') no-repeat center;
}

しかしなんでsedを使ったのかはわかりません

苦労した理由

svgはXMLなので書式にエラーがあればエラーを出すはずですが、

誤って生成したものをCSSに埋め込むとただ真っ白になるだけ。

かつ、誤って生成したエンコード済のdataスキーマのURLをブラウザに貼り付けても正常に表示されるため

error.svg
<svg><path fill="></svg>

ためしに100%エラーの出るsvgを上記に記載しましたが、
これが <img src= で読み込まれていたとしても
エラーが出ない理屈と同じなわけです

結論

CSSに埋め込むSVGは、マルチバイト文字がなければ、「#」と「 」(半角スペース)をエンコードすれば良い

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?