SVG Sprites mit symbol oder use

SVG Sprites ähneln den Image Sprites mit CSS. Statt eine SVG-Datei für jedes Symbol zu laden, liegen alle Symbole in einer SVG-Datei. In der einfachsten Variante holt SVG symbol ein einzelnes Icon oder die Icons werden über ein hash – das #-Symbol am Ende des Dateinamens – angesprochen.

SVG Icons und Sprites

Noch setzen die meisten Webseiten Icon-Fonts anstelle von SVG-Symbolen ein – ein kompliziertes Verfahren, bei dem Symbole, Icons oder kleine Grafiken in Zeichen eines Fonts umgewandelt werden.

Icon-Fonts sind zwar beliebig skalierbar, aber jedes Icon kann nur eine Farbe annehmen. Dazu kommt der Overhead, eine Grafik in ein Zeichen eines Fonts umzuwandeln, um es dann wieder als Grafik anzuzeigen. Da SVG Klartext ist, können wir schnell Änderungen an den Grafiken vornehmen, was bei Icon-Fonts nicht möglich ist.

In diesem Sinne ist auch das aktuelle WordPress-Theme Twentynineteen auf SVG-Icons umgestiegen und setzt SVG anstelle von Icon-Fonts ein (classes/class-twentynineteen-svg-icons.php), während die meisten WordPress-Themes noch auf FontAwesome setzen.

SVG-Icons in der HTML-Datei

Wenn nur eine begrenzte Zahl von Icons in die HTML-Seite gesetzt werden, lohnt es sich u.U., die Symbole nicht erst in eine SVG-Datei auszulagern, sondern inline ans Ende der HTML-Datei zu setzen. So muss nicht ein weiterer HTTP-Request für das Laden der SVG-Datei spendiert werden (sieht auch HTTP-Request)

…
<svg style="display:none">
<symbol id="fish" viewBox="0 0 140 140">
   <title>Fisch</title>
   <desc>Frische Fischgerichte</desc>
   <circle cx="70" cy="70" r="40" fill="seashell"/>
   <path fill-opacity=".6" fill="#c0c0c0" d="m64 46s-.7 2.7-2.6 5.3c-1.9 2.5-4 3.4-4 3.4s11.53 0 21.23 2.2c9.7 2 17.5 10.12 17.5 10.12s-.8-1.2-1.8-3.02c-1-1.8.8-4.4.8-4.4s-2.7.5-5.8-.2c-3-.6-3.9-5.2-3.9-5.2s-2.8.5-6 .5-3.6-4.5-3.6-4.5-4.5 1.2-7.7-.2c-3.13-1.4-4.03-4-4.03-4zm-2.5 10.7c-24.1 0-39.4 22.62-39.4 22.62l9 3.1h-6.8s8.2 16.7 27.9 20c.7 1.4 1.8 3.5 3.4 4.8 2.6 2 7.6 3.7 7.6 3.7s-3.3-2.9-3.7-5c-.2-.9-.3-2-.3-2.9 1.6 0 3.3-.1 5.1-.3 28.33-2.7 32.43-17.7 41.13-17.7 8.8 0 21 10.6 21 10.6l-11-16.9 11-14.66c-1.6 1.66-8.1 8.76-19.1 8.76-12.5 0-21.9-15.76-45.98-15.76zm5.93 5c2.1.8 3.6 3.1 3.6 5.22 0 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2.02-.6-4.12-2.2-5.22zm-18.03 1.3c5.2 2.62 7.6 10.12 7.6 16.82s-3 12.4-8.1 15.1c4-3.6 5.9-9 5.9-15.1 0-6.2-1.4-13.3-5.4-16.82zm-7.4 3.82c1.9 0 3.5 1.6 3.5 3.5s-1.6 3.5-3.5 3.5c-2 0-3.6-1.6-3.6-3.5s1.6-3.5 3.6-3.5zm34.03 1.2c2 .8 3.7 3.1 3.7 5.2 0 1.9-1.8 3.7-4 4.5 1.6-1.1 2.5-2.7 2.5-4.5 0-2-.5-4.1-2.2-5.2zm7.2 5.9c2.3.8 3.8 3.1 3.8 5.2 0 1.9-1.8 3.7-4 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.5-4.1-2.3-5.2zm-16 1.1c2.1.8 3.6 3.1 3.6 5.2 0 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.6-4.1-2.2-5.2zm7.9 6.2c2.1.8 3.7 3.1 3.7 5.2 0 1.9-1.8 3.7-3.9 4.5 1.6-1.1 2.4-2.7 2.4-4.5 0-2-.6-4.1-2.2-5.2zm-7.9 6.8c2.2.8 3.8 3.1 3.7 5.2.1 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.6-4.1-2.3-5.2z"/>
</symbol>
<symbol id="ice" viewBox="0 0 140 140">
   <title>Dessert</title>
   <circle cx="70" cy="70" r="40" fill="seashell"/>
   <path fill-opacity=".6" fill="#c0c0c0" d="m15.5 39h-1.6c6.9 6.64 6.6 11.74 10.1 19.64 2.9 6.4 5.8 11.6 10.5 15.1h-12.2c-1.5 0-2.9 1.3-2.9 2.9v.1c0 1.6 1.4 2.9 2.9 2.9h94.5c1.6 0 3-1.3 3-2.9v-.1c0-1.5-1.4-2.9-3-2.9h-26.4c.1-.7.2-1.4.2-2.1 0-8.9-7.4-16.1-16.5-16.1s-16.5 7.2-16.5 16.1c-1.6.7-3.3 1.3-5 1.5-4 .4-7.5-.9-10.5-2.8-5.4-3.3-9.1-8.6-11.5-14.2-1.6-3.8-3.8-7.3-6-10.8 1 1.1 2 2.3 2.9 3.5 2.8 3.2 4.6 7.1 6.8 10.7 2.1 3.7 5.2 6.8 8.9 9.1 3 1.8 6.8 2.2 10.2 2 1.1-.1 2.3 0 3.3-.4 2.2-3 .9-7.3-.4-10.1-.5-1.1-1-2.4-1.8-3.4-1.4.7-2.9 1.4-4.3 1.9 1-2.2 3.1-4.5 1.7-5.7-1.8-1.7-3.3-3.6-5.4-5-.9 1.5-1.7 3.1-2.7 4.4-.1-2.1-.1-4.3-.3-6.5-2.6-1.6-6.1-3.34-9.5-4.34-.6.2-.2 4.04-.5 5.74-.9-2.2-1.7-4.44-2.5-6.54-3.5-.80-11.1-1.7-15.5-1.7zm5.9 41.14c0 8.2 8.7 15.4 21.9 19.6h52.5c13.2-4.2 21.9-11.4 22-19.6h-96.4z" />
</symbol>
</svg>
</body>

Bei der Lösung mittels SVG-symbol-Tag kann jedes Icon ein title- und desc-Tag haben.

Elemente in einem symbol-Tag werden nicht gerendert, aber die SVG-Grafik nimmt trotzdem ihre volle Größe ein. Damit kein leerer Platz am Ende der Seite erscheint – display:none im öffnenden SVG-Tag.

Kein viewBox-Attribut im öffnenden SVG-Tag, sondern jedes symbol-Tag kann (anders als g-Tags für Gruppen) ein eigenes viewBox-Attribut enthalten.

<svg class="orange"><use xlink:href="#orange" /></svg>
<svg class="citro"><use xlink:href="#citro" /></svg>
<svg class="cherry"><use xlink:href="#cherry" /></svg>

Das Schöne an dieser Lösung: Die Icons müssen nicht mehr allesamt mit demselben Seitenverhältnis in die Seite eingesetzt werden, das Markup zum Einsetzen der Icons ist minimal und einfach.

Die SVG-Icons müssen dank eigenem viewBox-Attribut im symbol-Tag nicht übereinander liegen. Die Icon-Datei kann bequem mit einem grafischen SVG-Editor wie Inkscape oder Illustrator erstellt erstellt werden.

SVG Sprites in object- oder iframe-Tag

Wenn die Icons auf vielen Seiten verwendet werden, ist u.U. die ausgelagerte SVG-Datei im Vorteil – sie liegt beim nächsten Besuch schon im Cache. Genauso wie bei einem Icon-Font liegen alle Symbole oder Grafiken in einer einzigen SVG-Datei, allerdings liegen die einzelnen Grafiken oder Symbole übereinander gestapelt in der SVG-Grafik und sind nicht neben- oder untereinander aufgereiht.

Jedes Symbol liegt in einem SVG-Tag symbol mit einer ID. .display:none verhindert das Rendern der Symbole im HTML-Dokument.

.sprite:target { display: inline } überschreibt das display:none für ein einzelnes Symbol, das über ein # am Ende des Dateinamens im object-Tag identifiziert wird.

<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 140 140'>
<style>
   circle { fill: gainsboro; fill-opacity: 0.4}
   path { fill: hsl(225,40%,75%); fill-opacity: 0.8}
   .sprite { display:none}
   .sprite:target { display: inline; }
</style>
   <g id='fish' class="sprite">
      <circle r='40' cy='70' cx='70' />
      <path d='m 64,46 c 0,0 -0.7,2.7 -2.6,5.3 -1.9,2.5 -4,3.4 -4,3.4 0,0 11.53,0 21.23,2.2 9.7,2 17.5,10.12 17.5,10.12 0,0 -0.8,-1.2 -1.8,-3.02 -1,-1.8 0.8,-4.4 0.8,-4.4 0,0 -2.7,0.5 -5.8,-0.2 -3,-0.6 -3.9,-5.2 -3.9,-5.2 0,0 -2.8,0.5 -6,0.5 -3.2,0 -3.6,-4.5 -3.6,-4.5 0,0 -4.5,1.2 -7.7,-0.2 -3.13,-1.4 -4.03,-4 -4.03,-4 z m -2.5,10.7 c -24.1,0 -39.4,22.62 -39.4,22.62 l 9,3.1 -6.8,0 c 0,0 8.2,16.7 27.9,20 0,0 0,0 0,0 0.7,1.4 1.8,3.5 3.4,4.8 2.6,2 7.6,3.7 7.6,3.7 0,0 -3.3,-2.9 -3.7,-5 -0.2,-0.9 -0.3,-2 -0.3,-2.9 1.6,0 3.3,-0.1 5.1,-0.3 28.33,-2.7 32.43,-17.7 41.130002,-17.7 8.8,0 21,10.6 21,10.6 l -11,-16.9 11,-14.66 c -1.6,1.66 -8.1,8.76 -19.1,8.76 -12.500002,0 -21.900002,-15.76 -45.980002,-15.76 z m 5.93,5 c 2.1,0.8 3.6,3.1 3.6,5.22 0,1.9 -1.7,3.7 -3.9,4.5 1.7,-1.1 2.5,-2.7 2.5,-4.5 0,-2.02 -0.6,-4.12 -2.2,-5.22 z m -18.03,1.3 c 5.2,2.62 7.6,10.12 7.6,16.82 0,6.7 -3,12.4 -8.1,15.1 4,-3.6 5.9,-9 5.9,-15.1 0,-6.2 -1.4,-13.3 -5.4,-16.82 z m -7.4,3.82 c 1.9,0 3.5,1.6 3.5,3.5 0,1.9 -1.6,3.5 -3.5,3.5 -2,0 -3.6,-1.6 -3.6,-3.5 0,-1.9 1.6,-3.5 3.6,-3.5 z m 34.03,1.2 c 2,0.8 3.7,3.1 3.7,5.2 0,1.9 -1.8,3.7 -4,4.5 1.6,-1.1 2.5,-2.7 2.5,-4.5 0,-2 -0.5,-4.1 -2.2,-5.2 z m 7.2,5.9 c 2.3,0.8 3.8,3.1 3.8,5.2 0,1.9 -1.8,3.7 -4,4.5 1.7,-1.1 2.5,-2.7 2.5,-4.5 0,-2 -0.5,-4.1 -2.3,-5.2 z m -16,1.1 c 2.1,0.8 3.6,3.1 3.6,5.2 0,1.9 -1.7,3.7 -3.9,4.5 1.7,-1.1 2.5,-2.7 2.5,-4.5 0,-2 -0.6,-4.1 -2.2,-5.2 z m 7.9,6.2 c 2.1,0.8 3.7,3.1 3.7,5.2 0,1.9 -1.8,3.7 -3.9,4.5 1.6,-1.1 2.4,-2.7 2.4,-4.5 0,-2 -0.6,-4.1 -2.2,-5.2 z m -7.9,6.8 c 2.2,0.8 3.8,3.1 3.7,5.2 0.1,1.9 -1.7,3.7 -3.9,4.5 1.7,-1.1 2.5,-2.7 2.5,-4.5 0,-2 -0.6,-4.1 -2.3,-5.2 z' />
   </g>
   <g id='ice' class="sprite" transform="translate(-140)">
      <circle cx='210' cy='70' r='40' />
      <path d='m 160,39 c -0.6,0 -1.2,0 -1.6,0 6.9,6.64 6.6,11.74 10.1,19.64 2.9,6.4 5.8,11.6 10.5,15.1 l -12.2,0 c -1.5,0 -2.9,1.3 -2.9,2.9 l 0,0.1 c 0,1.6 1.4,2.9 2.9,2.9 l 94.5,0 c 1.6,0 3,-1.3 3,-2.9 l 0,-0.1 c 0,-1.5 -1.4,-2.9 -3,-2.9 l -26.4,0 c 0.1,-0.7 0.2,-1.4 0.2,-2.1 0,-8.9 -7.4,-16.1 -16.5,-16.1 -9.1,0 -16.5,7.2 -16.5,16.1 -1.6,0.7 -3.3,1.3 -5,1.5 -4,0.4 -7.5,-0.9 -10.5,-2.8 -5.4,-3.3 -9.1,-8.6 -11.5,-14.2 -1.6,-3.8 -3.8,-7.3 -6,-10.8 1,1.1 2,2.3 2.9,3.5 2.8,3.2 4.6,7.1 6.8,10.7 2.1,3.7 5.2,6.8 8.9,9.1 3,1.8 6.8,2.2 10.2,2 1.1,-0.1 2.3,0 3.3,-0.4 2.2,-3 0.9,-7.3 -0.4,-10.1 -0.5,-1.1 -1,-2.4 -1.8,-3.4 -1.4,0.7 -2.9,1.4 -4.3,1.9 1,-2.2 3.1,-4.5 1.7,-5.7 -1.8,-1.7 -3.3,-3.6 -5.4,-5 -0.9,1.5 -1.7,3.1 -2.7,4.4 -0.1,-2.1 -0.1,-4.3 -0.3,-6.5 -2.6,-1.6 -6.1,-3.34 -9.5,-4.34 -0.6,0.2 -0.2,4.04 -0.5,5.74 -0.9,-2.2 -1.7,-4.44 -2.5,-6.54 -3.5,-0.8 -11.1,-1.7 -15.5,-1.7 z m 5.9,41.14 c 0,8.2 8.7,15.4 21.9,19.6 l 52.5,0 c 13.2,-4.2 21.9,-11.4 22,-19.6 l -96.4,0 z' />
   </g>
</svg>

Im Dateinamen des object-Tags die Id des Icons mit dem # als Target setzen:

<object type="image/svg+xml" 
        width="100" height="100" 
        data="sprites.svg#fish"></object>
<object type="image/svg+xml" 
        width="100" height="100" 
        data="sprites.svg#shrimp"></object>
<object type="image/svg+xml" 
        width="100" height="100" 
        data="sprites.svg#coc"></object>

SVG-Icons in einer externen Datei

Statt das Icon aus der SVG-Datei über ein object- oder ein iframe-Tag einzubinden, würde ein einfaches SVG-Element schon reichen. Die Sonnenseite eines SVG use auf eine externe Datei liegt natürlich im Cache.

<svg class='icon'><use xlink:href='icons.svg#book'/></svg>
<svg class='icon'><use xlink:href='icons.svg#cup'/></svg>
<svg class='icon'><use xlink:href='icons.svg#genie'/></svg>

Diese Variante wird von allen modernen Browsern unterstützt, allerdings IE11 dafür nicht zu haben. Microsoft Edge hinkte lange Zeit ebenfalls hinterher, hat in einer der letzten Versionen nachgesetzt und zeigt externe Elemente über SVG use jetzt an.

Geht nicht: SVG mit ::before und ::after

Der Einsatz der SVG-Icons aus einer Datei (die gecacht werden kann) in der CSS-Datei äquivalent zu Icon-Fonts geht nicht:

.glyphicon-search:before{content:"\e003"}
.glyphicon-heart:before{content:"\e005"}
.glyphicon-star:before{content:"\e006"}
.glyphicon-star-empty:before{content:"\e007"}
Frische Orangen Orangen-Icon mit blauen Blättern Saure Zitrone Zitronen-Icon mit blauen Blättern Rote Kirschen Kirschen-Icon mit blauen Blättern