CSSのインラインSVG


283

CSSでインラインSVG定義を使用することは可能ですか?

私は次のようなものを意味します:

.my-class {
  background-image: <svg>...</svg>;
}

1
あなたは何をしようとしています、画像「ソース」をスタイルシートに追加しますか?
ズール

1
提案されたソリューションはCSSイメージの作業、HTMLではないということに注意してください<img>SVGは、いくつかの画像が混在している場合(埋め込まれた場合を除き)を参照してください、タグ、その他の場合に動作していない外部の画像を使用したマスクと背景画像SVGを、具体的には、SVGに制限がとして使用画像
Skippy le Grand Gourou

回答:


375

はい、可能です。これを試して:

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をネイティブでサポートしていません。


8
うまく機能しているように見える唯一のブラウザはSafari(5.1.4)です。Opera 11.62ではグラデーションは黒で、IE 9とFirefox 12では白です。Chrome 19では、SVGの幅/高さを%単位で指定しない限り機能します。実際の機能というよりも奇妙なものだと思います。しかし、それは素晴らしい発見です。
toniedzwiedz

4
右...こんな可愛いモンスターを同僚に見せたら、同僚の顔つきが気になるので、また見せてくれてありがとう。私はちょうど標準仕様に行って、それが事実上不可能であることが判明したと述べた(それが間違いであることが判明した)
toniedzwiedz

18
ここでの「ブラウザの非互換性」は、適切なURLエスケープの欠如がほとんどであり、内部のすべてがURLエスケープされているurl()必要があります。Opera、Firefox、Safariで正常に機能する例については、jsfiddle.net / 6WAtQを参照してください。
ErikDahlström12年

3
base64でエンコードされたsvgと非base64の間に互換性の違いはありますか?Base64では..私はちょうど使用インラインsvgsに思っている、私のCSSファイルをbloats
enapupe

4
文字セットを指定する標準的な方法は、「; utf8」の代わりに「; charset = UTF-8」を使用することに注意してください。tools.ietf.org/html/rfc2397
キースショー、

240

少し遅れますが、インラインSVGをバックグラウンドとして使用しようとして頭がおかしくなっている場合、上記のエスケープの提案はうまく機能しません。1つは、IEでは機能せず、SVGのコンテンツによっては、このテクニックがFFなどの他のブラウザーで問題を引き起こす場合があるためです。

svgをbase64エンコードする場合(URL全体ではなく、svgタグとそのコンテンツのみ!)、すべてのブラウザーで機能します。ここでは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を使用window.btoa()している場合は、を使用してbase64 svgを作成できます。そして、それが機能しない場合(文字列内の無効な文字について文句を言うかもしれません)、単に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の使用に関する優れた記事の1つはこちらです:http : //dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

お役に立てれば

マイク


2
ありがとう。Base64を使用したソリューションは優れたものでしたが、受け入れられた回答で問題が発生しました。
マルセル

1
あなたは私の命を救いました。私はクロームで機能しているがFFでは機能していないSVGボーダー画像を持っていました。今ではうまくいきます!:D
パピポ2014年

私も助けました(受け入れられた答えを試す時間を失った後)-これは間違いなく受け入れられた答えになるはずです。
カタイ

これがまだ機能しない場合は、ブラウザーのようにbase64でエンコードする前にxmlns属性をsvgelement 設定していることを確認してください<svg xmlns="http://www.w3.org/2000/svg">...</svg>
。svg

6年以上後も誰かがこの回答を見ている場合:base64 SVGのcss-tricks.com/probably-dont-base64-svg
Volker E.

38

まだ苦労している人のために、私はこれをすべての最新のブラウザーIE11以降で動作させることができました。

SASSを使用して、指定された色に基づいてSVGアイコンを生成したかったため、base64は私にとってオプションではありませんでした。例:@include svg_icon(heart, #FF0000);このようにして、特定のアイコンを任意の色で作成でき、CSSにSVG形状を1回埋め込むだけで済みます。(base64では、使用するすべての単色でSVGを埋め込む必要があります)

次の3つの点に注意してください。

  1. 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%20height%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


  1. データURLのUTF8文字セットを省略するデータURLを作成するとき、IE11で機能させるには文字セットを省略する必要があります。

    NOT background-image:url(data:image / svg + xml; utf-8、%3Csvg%2 ....)
    BUT background-image:url(data:image / svg + xml、%3Csvg%2 ... 。)


  1. RGB()INSTEAD OF HEXの色を使用する FirefoxはSVGコードの#を好みません。したがって、16進数のカラー値をRGB値に置き換える必要があります。

    NOT埋める= "#FF0000"
    BUT塗りつぶし= "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でインラインSVGに置き換えることができました。これは、圧縮後は約25 kbであることがわかりました。したがって、CSSファイルを肥大化させることなく、サイトが実行する必要のあるリクエストの量を制限する優れた方法です。


1
ところで、私が間違っているのなら修正してください。一度エンコードするrgb(255,0,0)必要がありrgb(255%2C0%2C0)ます。
カプセル

1
RGB文字列をエンコードしないことを意味し、それはまだ機能します。しかし、あなたが言ったようにそれをエンコードすることはおそらくより良いです。
Davy Baert

1
まあ、実際には、私はFirefoxでテストし%23ff0000て問題なく#ff0000動作しました
Capsule

1
@Capsule何が起こっているのかわかりませんが、%23ff0000はChromeとFFの両方で機能する唯一の方法です。#ff0000は機能せず、RGB(255,0,0)およびrgb(255%2C0%2C0)メソッドも機能しません。
表意文字

1
より少ないエンコーディングを必要とするメソッド(SCSSコードを含む):codepen.io/jakob-e/pen/doMoML
Sphinxxx

26

Mac / Linuxでは、次の単純なbashコマンドを使用して、SVGファイルをCSS背景属性の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ブログ投稿を参照してください。


2
読者の方へ:投票するだけでなく、あなたの意見をコメントしてください。そうすれば、あなたのコラボレーションでこの答えを改善できます!このようなQ&Aサイトではコラボレーションが不可欠です。ありがとうございました!
2015年

2
@LorDexコメントで提供したリンクは私の回答と同じです:)
araks

10

インラインSVGをCSSに埋め込むことと同じ問題があるCodePenデモをフォークしました。SCSSで機能するソリューションは、単純なurl-encoding関数を作成することです。

文字列置換関数は、組み込みのstr-slice、str-index関数から作成できます(Hugo Giraudelによるcss-tricksを参照)。

すると、ちょうど置き換え%<>"'との%xxコード:

@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;
}

image-inlineCompassにはヘルパー関数も用意されていますが、CodePenではサポートされていないため、このソリューションはおそらく役立つでしょう。

CodePenのデモ:http ://codepen.io/terabaud/details/PZdaJo/


1
私はまた、あなたが適切なCSSの背景値にSVGの文字列を変換することができますペン作成: s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb そうに、基本的に、あなたはあなたを貼り付け<svg><path></svg>、トップのテキストエリアに、それが直接の出力は、パスを消毒しますurl()値内。
LukyVj

1
これは素晴らしかった。ありがとうございました。1つのメモ。これをIEで機能させるには、; charset = utf8を使用する必要があります。
Daniel Lefebvre

4

サードパーティソース(Googleチャートなど)からのインラインSVGにはxmlns="http://www.w3.org/2000/svg"、SVG要素にXML名前空間属性()が含まれていない可能性があります(またはSVGがレンダリングされると削除される可能性があります。ブラウザインスペクタもブラウザコンソールのjQueryコマンドもSVG要素に名前空間を表示しません)。

これらのsvgスニペットを他のニーズ(CSSの背景画像またはHTMLのimg要素)に再利用する必要がある場合は、欠落している名前空間に注意してください。名前空間がないと、ブラウザーは(エンコーディングutf8またはbase64に関係なく)SVGの表示を拒否する可能性があります。


4

SVGのソリューションが1つ見つかりました。しかし、それはWebkitでのみ機能します。回避策をあなたと共有したいだけです。私の例では、フィルターを介してDOMからのSVG要素を背景として使用する方法を示しています(background-image:url( '#glyph')が機能していません)。

このSVGアイコンのレンダリングに必要な機能:

  1. CSSを使用してHTML要素にSVGフィルター効果を適用する(IEとEdgeはサポートしていません)
  2. feImageフラグメントのロードのサポート(firefoxはサポートしていません)

.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>

もう1つの解決策は、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>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.