CSSでインラインSVG定義を使用することは可能ですか?
私は何かを意味します:
.my-class {
background-image: <svg>...</svg>;
}
はい、可能です。これを試して:
body { background-image:
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
}
(これを機能させるにはSVGコンテンツをURLエスケープする必要があることに注意してください。例えば#
は%23
に置き換えられます。)
これはIE 9(これはSVGをサポートします) で動作します。データURLは古いバージョンのIEでも機能します(制限付き)が、SVGをネイティブにサポートしていません。
少し遅れましたが、インラインSVGを背景として使用しようとして狂っている人の場合、上記のエスケープ方法はうまくいきません。一つには、それはIEでは動作しません、そしてあなたのSVGの内容に依存してそのテクニックはFFのような他のブラウザで問題を引き起こすでしょう。
Svg(URL全体ではなく、svgタグとその内容だけ)をbase64エンコードすると、すべてのブラウザで機能します。これはbase64と同じjsfiddleの例です。 http://jsfiddle.net/vPA9z/3/
CSSはこのようになりました:
body { background-image:
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");
Base64に変換する前に、必ずエスケープするURLを削除してください。つまり、上記の例ではcolor = '#fcc'がcolor = '%23fcc'に変換されていました。#に戻ってください。
Base64がうまく機能する理由は、一重引用符と二重引用符、およびURLのエスケープに関する問題がすべて解消されるためです。
あなたがJSを使っているなら、あなたはあなたのbase64 svgを生成するためにwindow.btoa()
を使うことができます。それでもうまくいかない場合(文字列中の無効な文字について文句を言うかもしれません)、単に https://www.base64encode.org/ を使うことができます。
Divの背景を設定する例:
var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
var mySVG64 = window.btoa(mySVG);
document.getElementById('myDiv').style.backgroundImage = "url('data:image/svg+xml;base64," + mySVG64 + "')";
html, body, #myDiv {
width: 100%;
height: 100%;
margin: 0;
}
<div id="myDiv"></div>
JSでは、パラメータを変更しても、その場でSVGを生成できます。
SVGを使用する上でより良い記事の一つはここにあります: http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/
お役に立てれば
マイク
まだ苦労している人たちのために、私はこれがIE11以上のすべての現代的なブラウザでうまくいくようにしました。
sASSを使用して任意の色に基づいてSVGアイコンを生成したいので、base64は私には選択肢がありませんでした。例:@include svg_icon(heart, #FF0000);
このように私は任意の色で特定のアイコンを作成することができ、CSSにSVGの形を一度埋め込むだけでよいです。 (base64では、使用したいすべての色にSVGを埋め込む必要があります)
注意すべき点が3つあります。
あなたのSVGをURLエンコードする他の人が示唆しているように、あなたはそれがIE11で動作するためにあなたの全体のSVG文字列をURLエンコードする必要があります。私の場合は、fill="#00FF00"
やstroke="#FF0000"
のようなフィールドの色の値を省略し、それらをSASS変数fill="#{$color-rgb}"
に置き換えて、必要な色に置き換えることができます。文字列の残りの部分をURLエンコードするには、 任意のオンラインコンバータ を使用できます。あなたはこのようなSVG文字列で終わるでしょう:
%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D% 27512%27%20高さ3D 3D 27512%27%3E%0A%20%20%3Cpath%20d%3D 27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%2041.012%2010.535%2079.541 %2028.973%20113.104L3.825%20464.586c345%2012.797%2041.813%2012.797%2015.467%200%2029.872-4.721%2041.813-12.797v158.184z%27%20fill%3D%27#{ $ color-rgb}%27%2F%3E%3C%2Fsvg%3E
データURL内のUTF8文字を削除するデータURLを作成するときは、IE11で機能するために文字セットを省略する必要があります。
_ではないbackground-image:url(データ:image/svg + xml; utf-8、%3Csvg%2 ....)
BUTbackground-image:url(データ:image/svg + xml、%3Csvg%2 ....)
RGB()16進数の色の代わりに使用FirefoxはSVGコードの#を好みません。そのため、カラーの16進数値をRGBのものに置き換える必要があります。
NOTfill = "#FF0000"
BUTfill = "rgb(255,0,0)"
私の場合、SASSを使って与えられた16進数を有効なRGB値に変換します。コメントで指摘されているように、それは同様にあなたのRGB文字列をURLエンコードするのが最善です(コンマは%2Cになります)
@mixin svg_icon($id, $color) {
$color-rgb: "rgb(" + red($color) + "%2C" + green($color) + "%2C" + blue($color) + ")";
@if $id == heart {
background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%204%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E');
}
}
私はこれが非常に複雑なSVG(インラインSVGがその場合決してない)のための最善の解決策ではないかもしれないことを理解します、しかしほんの2、3色のフラットアイコンのためにこれが本当にうまくいく。
私はCSSの中でSpriteビットマップ全体を省いてそれをインラインSVGに置き換えることができました。そして、それは圧縮後にはたった25kbであることが判明しました。 CSSファイルを肥大化させることなく、あなたのサイトがしなければならないリクエストの量を制限するための素晴らしい方法です。
Mac/Linuxでは、次の単純なbashコマンドを使用して、SVGファイルをCSSのbackground属性用のbase64エンコード値に簡単に変換できます。
echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"
Mac OS Xでテスト済み。このようにしても、URLのエスケープによる混乱を防ぐことができます。
SVGファイルをbase64でエンコードするとサイズが大きくなることを忘れないでください。 css-tricks.comブログ投稿 を参照してください。
CSSにインラインSVGを埋め込むのと同じ問題を抱えていたCodePenデモをフォークしました。 SCSSと連携する解決策は、単純なURLエンコード機能を構築することです。
文字列置換関数は組み込みのstr-slice、str-index関数から作ることができます(Hugo Giraudelのおかげで css-tricks を見てください)。
次に、%
、<
、>
、"
、'
を%xx
codesに置き換えます。
@function svg-inline($string){
$result: str-replace($string, "<svg", "<svg xmlns='http://www.w3.org/2000/svg'");
$result: str-replace($result, '%', '%25');
$result: str-replace($result, '"', '%22');
$result: str-replace($result, "'", '%27');
$result: str-replace($result, ' ', '%20');
$result: str-replace($result, '<', '%3C');
$result: str-replace($result, '>', '%3E');
@return "data:image/svg+xml;utf8," + $result;
}
$mySVG: svg-inline("<svg>...</svg>");
html {
height: 100vh;
background: url($mySVG) 50% no-repeat;
}
Compassには image-inline
ヘルパー関数もありますが、CodePenではサポートされていないので、この解決法はおそらく有用でしょう。
CodePenのデモ: http://codepen.io/terabaud/details/PZdaJo/
(Googleのチャートのような)サードパーティのソースからのインラインSVGは、SVG要素にXML名前空間属性(xmlns="http://www.w3.org/2000/svg"
)を含まないかもしれません。
他のニーズ(CSSのbackground-imageまたはHTMLのimg要素)のためにこれらのsvgスニペットを再利用する必要があるときは、不足している名前空間に注意してください。ネームスペースがないと、ブラウザはSVGの表示を拒否することがあります(utf8またはbase64のエンコーディングに関係なく)。
私はSVGに一つの解決策を見つけました。しかし、それはWebkitだけのための仕事です、私はただあなたと私の回避策を共有したいです。私の例では、フィルタを通してDOMとしてSVG要素を背景として使用する方法が示されています(background-image:url( '#glyph')が機能していません)。
このSVGアイコンのレンダリングに必要な機能:
.test {
/* background-image: url('#glyph');
background-size:100% 100%;*/
filter: url(#image);
height:100px;
width:100px;
}
.test:before {
display:block;
content:'';
color:transparent;
}
.test2{
width:100px;
height:100px;
}
.test2:before {
display:block;
content:'';
color:transparent;
filter: url(#image);
height:100px;
width:100px;
}
<svg style="height:0;width:0;" version="1.1" viewbox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="glyph">
<path id="heart" d="M100 34.976c0 8.434-3.635 16.019-9.423 21.274h0.048l-31.25 31.25c-3.125 3.125-6.25 6.25-9.375 6.25s-6.25-3.125-9.375-6.25l-31.202-31.25c-5.788-5.255-9.423-12.84-9.423-21.274 0-15.865 12.861-28.726 28.726-28.726 8.434 0 16.019 3.635 21.274 9.423 5.255-5.788 12.84-9.423 21.274-9.423 15.865 0 28.726 12.861 28.726 28.726z" fill="crimson"/>
</g>
<svg id="resized-glyph" x="0%" y="0%" width="24" height="24" viewBox="0 0 100 100" class="icon shape-codepen">
<use xlink:href="#glyph"></use>
</svg>
<filter id="image">
<feImage xlink:href="#resized-glyph" x="0%" y="0%" width="100%" height="100%" result="res"/>
<feComposite operator="over" in="res" in2="SourceGraphic"/>
</filter>
</defs>
</svg>
<div class="test">
</div>
<div class="test2">
</div>
もう一つの解決策は、URLエンコードを使用することです
var container = document.querySelector(".container");
var svg = document.querySelector("svg");
var svgText = (new XMLSerializer()).serializeToString(svg);
container.style.backgroundImage = `url(data:image/svg+xml;utf8,${encodeURIComponent(svgText)})`;
.container{
height:50px;
width:250px;
display:block;
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
}
<svg height="100" width="500" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
</svg>
<div class="container"></div>