it-swarm.com.de

Inline-SVG in CSS

Ist es möglich, eine Inline-SVG-Definition in CSS zu verwenden?

Ich meine so etwas wie:

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

Ja, es ist möglich. Versuche dies:

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>");
      }

(Beachten Sie, dass der SVG-Inhalt mit einem URL-Escape versehen werden muss, damit dies funktioniert, z. B. # wird ersetzt durch %23.)

Dies funktioniert in IE 9 (unterstützt SVG) . Daten-URLs funktionieren auch in älteren Versionen von IE (mit Einschränkungen) , aber sie unterstützen SVG nicht von Haus aus.

317
Raab

Ein bisschen spät, aber wenn einer von Ihnen verrückt geworden ist und versucht hat, Inline-SVG als Hintergrund zu verwenden , funktionieren die obigen Vorschläge nicht ganz. Zum einen funktioniert es nicht im IE und abhängig vom Inhalt Ihres SVG wird die Technik in anderen Browsern, wie FF, Probleme verursachen.

Wenn Sie base64 das svg (nicht die gesamte URL, nur das svg-Tag und seinen Inhalt!) Codieren, funktioniert es in allen Browsern. Hier ist dasselbe jsfiddle-Beispiel in base64: http://jsfiddle.net/vPA9z/3/

Das CSS sieht nun so aus:

body { background-image: 
    url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");

Denken Sie daran, alle URLs zu entfernen, bevor Sie zu base64 konvertieren. Mit anderen Worten, im obigen Beispiel wurde color = '# fcc' in color = '% 23fcc' konvertiert. Sie sollten zu # zurückkehren.

Der Grund, warum base64 besser funktioniert, ist, dass es alle Probleme mit einfachen und doppelten Anführungszeichen und URLs beseitigt

Wenn Sie JS verwenden, können Sie window.btoa() verwenden, um Ihr base64-SVG zu erstellen. und wenn es nicht funktioniert (es könnte sich über ungültige Zeichen in der Zeichenkette beschweren), können Sie einfach https://www.base64encode.org/ verwenden.

Beispiel um einen div Hintergrund zu setzen:

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>

Mit JS können Sie SVGs im laufenden Betrieb generieren und sogar deren Parameter ändern.

Einer der besseren Artikel zur Verwendung von SVG ist hier: http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

Hoffe das hilft

Mike

207
Mike Tommasi

Für Leute, die immer noch Probleme haben, ist es mir gelungen, dies auf allen modernen Browsern ab IE11 zum Laufen zu bringen.

base64 war für mich keine Option, da ich SASS verwenden wollte, um SVG-Symbole basierend auf einer bestimmten Farbe zu generieren. Zum Beispiel: @include svg_icon(heart, #FF0000); Auf diese Weise kann ich ein bestimmtes Symbol in einer beliebigen Farbe erstellen und muss die SVG-Form nur einmal in das CSS einbetten. (Mit base64 müssen Sie die SVG-Datei in jede einzelne Farbe einbetten, die Sie verwenden möchten.)

Es gibt drei Dinge, die Sie beachten müssen:

  1. URL KODIEREN SIE IHR SVG Wie andere vorgeschlagen haben, müssen Sie Ihre gesamte SVG-Zeichenfolge per URL kodieren, damit sie in IE11 funktioniert. In meinem Fall habe ich die Farbwerte in Feldern wie fill="#00FF00" Und stroke="#FF0000" Weggelassen und durch eine SASS-Variable fill="#{$color-rgb}" Ersetzt, damit diese durch die gewünschte Farbe ersetzt werden können . Sie können einen beliebigen Online-Konverter verwenden, um den Rest der Zeichenfolge per URL zu kodieren. Am Ende erhalten Sie eine SVG-Zeichenfolge wie die folgende:

    % 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. UTF8-ZEICHEN IN DER DATEN-URL AUSLASSEN Wenn Sie Ihre Daten-URL erstellen, müssen Sie den Zeichensatz weglassen, damit er in IE11 funktioniert.

    [~ # ~] nicht [~ # ~] Hintergrundbild: URL (Daten: image/svg + xml; utf-8,% 3Csvg% 2 ....)
    [~ # ~] aber [~ # ~] Hintergrundbild: URL (Daten: image/svg + xml,% 3Csvg % 2 ....)


  1. BENUTZEN SIE RGB () STATT HEX-Farben Firefox mag kein # im SVG-Code. Sie müssen also Ihre Farbhex-Werte durch RGB-Werte ersetzen.

    [~ # ~] nicht [~ # ~] fill = "# FF0000"
    [~ # ~] aber [~ # ~] fill = "rgb (255,0,0)"

In meinem Fall verwende ich SASS, um ein gegebenes Hex in einen gültigen RGB-Wert umzuwandeln. Wie in den Kommentaren erwähnt, ist es am besten, die RGB-Zeichenfolge auch per URL zu kodieren (so wird das Komma zu% 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');
   }
}

Mir ist klar, dass dies nicht die beste Lösung für sehr komplexe SVGs ist (Inline-SVG gibt es in diesem Fall nie), aber für flache Symbole mit nur wenigen Farben funktioniert dies wirklich hervorragend.

Ich konnte eine ganze Sprite-Bitmap weglassen und durch Inline-SVG in meinem CSS ersetzen, das sich nach der Komprimierung als nur etwa 25 KB groß herausstellte. Auf diese Weise können Sie die Anzahl der Anfragen auf Ihrer Website begrenzen, ohne Ihre CSS-Datei zu überladen.

32
Davy Baert

Unter Mac/Linux können Sie eine SVG-Datei mit diesem einfachen bash-Befehl einfach in einen base64-codierten Wert für das CSS-Hintergrundattribut konvertieren:

echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"

Getestet unter Mac OS X. Auf diese Weise vermeiden Sie auch, dass die URL durcheinander kommt.

Denken Sie daran, dass die Base64-Codierung einer SVG-Datei ihre Größe erhöht (siehe css-tricks.com-Blogpost ).

24
araks

Ich habe eine CodePen-Demo erstellt, die das gleiche Problem mit der Einbettung von Inline-SVG in CSS hatte. Eine Lösung, die mit SCSS funktioniert, besteht darin, eine einfache URL-Codierungsfunktion zu erstellen.

Aus den eingebauten Funktionen str-slice und str-index kann eine String-Ersetzungsfunktion erstellt werden (siehe css-tricks , danke an Hugo Giraudel).

Dann ersetzen Sie einfach %, <, >, ", ', mit dem %xxcodes:

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

Da ist auch ein image-inline Hilfefunktion in Compass verfügbar, aber da sie in CodePen nicht unterstützt wird, ist diese Lösung möglicherweise hilfreich.

Demo auf CodePen: http://codepen.io/terabaud/details/PZdaJo/

10
Lea Rosema

Inline-SVG aus Quellen von Drittanbietern (z. B. Google Charts) enthält möglicherweise kein XML-Namespace-Attribut (xmlns="http://www.w3.org/2000/svg") im SVG-Element (oder möglicherweise nach dem Rendern von SVG entfernt - weder der Browser-Inspektor noch die jQuery-Befehle der Browserkonsole zeigen den Namespace im SVG-Element an).

Wenn Sie diese SVG-Snippets für andere Zwecke verwenden müssen (Hintergrundbild in CSS oder img-Element in HTML), achten Sie auf den fehlenden Namespace. Ohne den Namespace können Browser die Anzeige von SVG verweigern (unabhängig von der Kodierung utf8 oder base64).

4
mp31415

Ich habe eine Lösung für SVG gefunden. Aber es funktioniert nur mit Webkit. Ich möchte nur meine Problemumgehung mit Ihnen teilen. In meinem Beispiel wird gezeigt, wie ein SVG-Element aus DOM als Hintergrund durch einen Filter verwendet wird (Hintergrundbild: url ('# glyph') funktioniert nicht).

Funktionen, die für dieses SVG-Symbol erforderlich sind:

  1. Anwenden von SVG-Filtereffekten auf HTML-Elemente mithilfe von CSS (IE und Edge werden nicht unterstützt)
  2. feImage Fragment Load Support (Firefox nicht unterstützt)
.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>

Eine weitere Lösung ist die Verwendung von URL-Codierung

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>
3
Alex Nikulin