SVG/Tutorials/Icons

Aus SELFHTML-Wiki
< SVG‎ | Tutorials
Wechseln zu: Navigation, Suche
SVG-Icons zeichnen sich gegenüber kleinen Grafiken oder Icon-Fonts durch viele Vorteile aus, da sie
  • jederzeit direkt bearbeitet werden können
  • als Vektorgrafiken immer gestochen scharf skalierbar sind
  • durch CSS und mit den Möglichkeiten von SVG mehrfarbig gestaltet, mit CSS-Filtern verändert und sogar animiert werden können.
  • ebenfalls in Sprites zusammengefasst werden können. Das sind kleine Grafiken,[1] die als Icons Webseiten visuell bereichern, aber nicht im HTML auftauchen. Der Einsatz von SVG-Grafiken gegenüber CSS-Sprites oder Icon-Fonts hat mehrere Vorteile.

SVG-Grafiken sind …

Neben der herkömmlichen Einbindung als Bild oder Hintergrundbild können Sie SVGs auch direkt im HTML-Markup einbinden.

SVGs optimieren

Oft ist es schneller und einfacher, SVG-Grafiken mit einem Bildbearbeitungsprogramm wie Adobe Illustrator oder Inkscape zu erstellen und dann einzubinden. Allerdings sind viele im Netz vorhandene SVG-Icons mit Zeichenprogrammen wie Illustrator erstellt und daher unnötig kompliziert, wie dieses Beispiel aus dem Forum zeigt.[2]

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" height="160" width="160" version="1.0">
 <g fill="#4b4b4b">
  <path d="m80 15c-35.88 0-65 29.12-65 65s29.12 65 65 65 65-29.12 65-65-29.12-65-65-65zm0 10c30.36 0 55 24.64 55 55s-24.64 55-55 55-55-24.64-55-55 24.64-55 55-55z"/>
  <path d="m57.373 18.231a9.3834 9.1153 0 1 1 -18.767 0 9.3834 9.1153 0 1 1 18.767 0z" transform="matrix(1.1989 0 0 1.2342 21.214 28.75)"/>
  <path d="m90.665 110.96c-0.069 2.73 1.211 3.5 4.327 3.82l5.008 0.1v5.12h-39.073v-5.12l5.503-0.1c3.291-0.1 4.082-1.38 4.327-3.82v-30.813c0.035-4.879-6.296-4.113-10.757-3.968v-5.074l30.665-1.105"/>
 </g>
</svg>

Sie können sie aber mit wenigen Schritten optimieren, sodass sie schneller vom Browser geladen werden.[3] Bei kleineren Grafiken kann dies von Hand geschehen, im Allgemeinen empfiehlt sich jedoch der Einsatz eines Code-Optimierers.

Empfehlung:
Verwenden Sie nur optimierte SVG-Grafiken, da …
  • SVG-Grafiken keine Hardware-Unterstützung durch die Grafikkarte genießen
  • der Code verständlicher wird
  • es späteres Editieren vereinfacht.

überflüssige XML-Metadaten

Wenn Sie eine in Inkscape oder Illustrator erstellte Datei im Quelltext anschauen, sind die ersten 60 Zeilen weitgehend überflüssig:[4]

Datenmüll
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.5 r10040"
   sodipodi:docname="Neues Dokument 1">
  <defs
     id="defs4">
    <inkscape:perspective
       sodipodi:type="inkscape:persp3d"
       inkscape:vp_x="0 : 526.18109 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_z="744.09448 : 526.18109 : 1"
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
       id="perspective2985" />
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.35"
     inkscape:cx="350"
     inkscape:cy="520"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1920"
     inkscape:window-height="1018"
     inkscape:window-x="-8"
     inkscape:window-y="-8"
     inkscape:window-maximized="1" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
alles, was man braucht!
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160">
<title>Seitenname</title>
<desc>aussagefähige Beschreibung</desc>

Die Breite und Höhe des SVG-Elements wird hier im CSS notiert, nur der Viewport wird durch das viewBox-Attribut festgelegt.

In HTML5 können Sie die XML-Dokumenttypdeklaration und die Namensräume des svg-Elements weglassen.

Daneben finden sich XML-Metadaten sowohl für Inkscape, als auch für den Vorläufer sodipodi, der seit 2004 nicht mehr weiterentwickelt wird,[5] und Metadaten im rdf-Format, die alle gelöscht werden können. Sie sind für die Anzeige von SVG-Grafiken nicht notwendig.

Empfehlung: Fügen Sie SVG-Dokumenten einen title und eine aussagefähige Beschreibung mit einem desc-Element hinzu.

Präsentationsattribute

Grafik-Programme fügen oft für jedes Element Präsentationsattribute mit Standardwerten hinzu. Da die Browser diese Werte sowieso als Default rendern würden, können Sie sie auch löschen.

überflüssige Defaultwerte
<path style="fill: black;
fill-rule: nonzero;
font-style: normal;
font-weight: normal;
fill-opacity: 1;
stroke-width: 1;
stroke-linecap: butt;
stroke-linejoin: miter;
stroke-miterlimit: 4;
stroke-opacity: 1;
stroke-dasharray: none;" />
Empfehlung: Falls Sie Präsentationsattribute mit anderen Werten haben, die mehrfach auftreten, fassen Sie sie in Klassen zusammen. Diese können Sie dann zentral im Stylesheet definieren und verändern.

Das optimierte Icon

Häufig ist es besser kreisrunde Formen nicht mit komplizierten Pfaden, sondern wirklich mit dem circle-Element zu realisieren.

optimiertes SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 140">
  <circle stroke="currentColor" stroke-width="10" cx="70" cy="70" r="60"/>
  <circle cx="69" cy="39" r="11" fill="currentColor" />
  <path fill="currentcolor"	
        d="M80 100c0 3 1.6 3.9 4 4l5 0.1v5h-38v-5l5-0.12.4-0.1 4-1 4-4v-31c0-4.4-6-4-9-3.9v-5l29-1"/>
</svg>

Durch die Farbangabe currentColor wird die Textfarbe des aktuellen Abschnitts automatisch übernommen. So können diese Icons ohne weitere Anpassung z. B. im Dark Mode verwendet werden.

SVG-Sprites

Ausgangspunkt war die Frage im SELF-Forum, ob man eine png-Grafik mit transparentem Hintergrund mittels CSS färben könne.[6] Dies ist so nicht möglich; für jede Farbe müsste eine Rastergrafik erstellt und gehostet werden, die dann bei einer Änderung des Farbkonzepts erneut angepasst werden müsste.

Gunnar Bittersmann postete ein Tutorial, das im Februar 2020 überarbeitet und ins SELF-Wiki übertragen wurde.[7]


SVG erstellen

Als erstes wird das PNG in einem Bildbearbeitungsprogramm geöffnet und die Koordinaten der Eckpunkte des Hauses ausgelesen. Die ergeben dann als Pfad:

Haus als Vektorpfad
<svg xmlns="http://www.w3.org/2000/svg">
	<symbol id="house" viewBox="0 0 80 80">
		<path d="M40,13 L1,48 H12 V80 H32 V56 H48 V80 H68 V48 H79z"/>
	</symbol>
</svg>

Erwähnenswert ist, dass nicht das svg-Element, sondern das symbol-Element hier das viewBox-Attribut trägt. 0 0 heißt, dass der Punkt links oben der Punkt (0, 0), also der Koordinatenursprung ist. Die x-Achse zeigt nach rechts; die y-Achse nach unten.

Die anderen beiden Zahlen geben an, dass die Zeichenfläche 80 Einheiten breit und 80 Einheiten hoch ist. Ich habe die viewBox mal so gelegt, dass sie vom Haus weitgehend ausgefüllt wird: 0 0 80 80. Dann stehen die Häuser auf der Erde Grundlinie des Texts.

Wichtig ist hier, dass es sich bei SVG um eine Längeneinheit handelt, nicht um Pixel. Man würde dasselbe Ergebnis erhalten, wenn man 0 0 400 800 setzt und bei den Koordinaten alle x-Werte mit 5 und alle y-Werte mit 10 multipliziert.

Der Pfad:

  • M40,13: Move to Punkt (40, 13) – die Spitze des Daches
  • L1,48: Line to Punkt (1, 48) – das linke untere Ende des Daches
  • H12: Horizontal line to x = 12, y bleibt gleich, d. h. zum Punkt (12, 48) – Hauswand links oben
    (Ich hätte auch L12,48 schreiben können; das ist aber länger.)
  • V80: Vertical line to y = 80, x bleibt gleich, d. h. zum Punkt (12, 80) – Hauswand links unten
    (Ich hätte auch L12,80 schreiben können; das ist aber länger.)
    usw. bis H79 zum letzten Punkt (80, 48) – rechtes unteres Ende des Daches
  • z: schließe die Kontur, d. h. Linie zurück zum Ausgangspunkt (40, 13) – der Spitze des Daches

SVG in HTML

Da SVG als XML-Dialekt direkt in HTML eingebunden werden kann, können Sie die Definitionen für Ihre Icons direkt in Ihre Webseiten integrieren. Das Ganze in eine HTML-Datei (in den body) gepackt und wir sehen … nichts! symbol ist nicht dazu gedacht angezeigt zu werden, sondern dazu, dass man sich das von anderswo holen kann.

Allerdings wird Platz für das svg-Element freigehalten. Da wir das nicht wollen, ergänzen wir die erste Zeile zu:

HTML-Datei mit SVG-Sprite ansehen …
<svg style="display: none">

(Das hidden-Attribut gibt’s für svg-Elemente nicht; <svg hidden> funktioniert nicht.)

„Von anderswo holen“ heißt für uns jetzt: ein weiteres svg-Element.

HTML-Datei mit SVG-Sprite ansehen …
<svg>
	<use href="#house"/>
</svg>

use verwendet ein anderes Element und der Fragmentbezeichner (fragment-identifier) href="#house" gibt an, welches. Das bezieht sich auf das Element mit der ID house – das ist das symbol im anderen svg-Element. (Dass IDs eindeutig sein müssen, also house nicht als ID eines HTML-Elements in diesen HTML-Dokument auftreten darf, versteht sich von selbst.)

Empfehlung: In SVG2 wurde die Referenzierung mit XLink durch die in HTML gebräuchliche mit dem href-Attribut ersetzt. Dies wird (Stand: August 2019) von allen Browsern (sogar IE9-11) verstanden - einzige Ausnahme bilden ältere Versionen des Safari-Browsers (iOS <12).
Da das xlink:href bestimmt nicht entfernt wird, ist es empfehlenswert, vorerst noch die eigentlich obsolete Variante zu verwenden.--Matthias Scharwies (Diskussion) 12:00, 1. Aug. 2019 (CEST)

Zum Schluss sei noch erwähnt, dass bei in HTML eingebettetem SVG keine XML-Namenraumangaben nötig sind.

Beachten Sie: Safari iOS stellt keine Icons dar, wenn die Referenzierung mit use vor dem Laden der symbol-Elemente erfolgt. Stellen Sie das SVG-Fragment daher vor ihren HTML-Code.


Et voilà! Das Haus sollte jetzt angezeigt werden – in irgendeiner Größe. Und in schwarz, weil wir im SVG keine Farbe angegeben haben. Das wollen wir auch nicht – dazu kommen wir später.

Und wenn wir dasselbe Icon nochmal haben wollen: noch ein svg mit use-Element. Als Beispiel gleich mit etwas Text drumrum:

HTML-Datei mit SVG-Sprite 2 ansehen …
<p>
	Home
	<svg>
		<use href="#house"/>
	</svg>
	<a href="">
		sweet home
		<svg>
			<use href="#house"/>
		</svg>
	</a>
</p>

SVG mit CSS gestalten

Nun wollen wir nicht irgendeine Größe; und auch die Farbe festlegen. Das können wir im Stylesheet tun, wo bspw. auch die Angaben zur Farbe von Links einschließlich Hover- und Focus-Effekt (für Tastaturbedienung!) stehen:

SVG-Sprites mit CSS gestalten ansehen …
a { color: steelblue }
a:focus, a:hover { color: red; }
			
svg {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

Für SVG-Elemente gibt es teilweise andere CSS-Eigenschaften als für HTML-Elemente, wie hier fill. Damit können wir die Icons mit einer Farbe füllen, bspw. fill: rebeccapurple.

Wir können aber auch mit dem Schlüsselwort currentColor für die Icons jeweils die aktuelle Textfarbe übernehmen. In unserem Beispiel ist das für das erste Haus schwarz und für das zweite – wo das svg innerhalb des a-Elements ist – steelblue.

Und wenn sich beim Drüberfahren mit der Maus oder Fokussieren mit der Tastatur die Farbe des Links auf red; ändert, dann ändert sich die Farbe des Icons mit!

Aber eigentlich soll gar nicht alles SVG in HTML eingebettet sein.

Einbindung externer svg-Dateien

Was, wenn wir nun mehrere verschiedene Icons haben: Mein Haus, mein Auto, mein Boot, …?

Die sammeln wir alle als symbols im ersten svg-Element:

mehrere Icons als Sprites
<svg style="display: none">
	<symbol id="house" viewBox="0 0 96 96">
		<path d="M40,13 L1,48 H12 V80 H32 V56 H48 V80 H68 V48 H79z"/>
	</symbol>
	<symbol id="car" viewBox="0 0 100 200">
		<path d="…"/>
	</symbol>
	<symbol id="boat" viewBox="-21 -21 42 42">
		<path d="…"/>
	</symbol>
</svg>

Die Pfade für Auto und Boot habe ich nur angedeutet. You get the picture. (No pun intended.)

Wichtig ist, dass jedes symbol sein eigenes viewBox-Attribut, d. h. sein eigenes Koordinatensystem hat. Das hat nichts mit der Größe zu tun, mit der das Icon dargestellt wird; diese hatten wir im Stylesheet mit svg { width: 1em; height: 1em } angegeben.

(Man kann natürlich auch für verschiedene Icons verschiedene Größen angeben oder dasselbe Icon an verschiedenen Stellen in verschiedenen Größen verwenden.)

Verwendung der SVG-Sprites ansehen …
<ul>
	<li><svg><use href="#house"/></svg> mein Haus</li>
	<li><svg><use href="#car"/></svg>   mein Auto</li>
	<li><svg><use href="#boat"/></svg>  mein Boot</li>
</ul>

Nun wollen wir die Icons nicht nur auf einer Webseite, sondern auf allen Seiten unserer Website einsetzen. Dazu müssten wir das svg-Element mit den symbols in jedes HTML-Dokument hineinkopieren … was wohl keine so gute Lösung wäre.

Sinnvoll ist, das svg-Element mit den symbols in eine Datei auszulagern (bspw. speichern als icons.svg). style="display: none" kann dann weg; wichtig ist, dass hier die XML-Namensraumangabe vorhanden ist:

<svg xmlns="http://www.w3.org/2000/svg">

Diese Datei wird nun nicht mit PHP o.ä. in den HTML-Quelltext geschrieben, denn dann müssten ja sämtliche Icons bei jeder Seite erneut übertragen werden. Das würde den Quelltext unnötig aufblähen, insbesondere, wenn wir nicht nur drei, sondern dreiundzwölfzig Icons in unserer Sammlung haben.

Wir wollen, dass diese SVG-Datei mit allen Icons nur einmal übertragen wird und dann im Browsercache liegt. Wir holen uns die Icons deshalb aus der externen Datei:

SVG-Sprites mit CSS gestalten ansehen …
<ul>
	<li><svg><use href="/assets/icons.svg#house"/></svg> mein Haus</li>
	<li><svg><use href="/assets/icons.svg#car"/></svg>   mein Auto</li>
	<li><svg><use href="/assets/icons.svg#boat"/></svg>  mein Boot</li>
</ul>

bzw.

<ul>
	<li><svg><use href="https://example.net/assets/icons.svg#house"/></svg> mein Haus</li>
	<li><svg><use href="https://example.net/assets/icons.svg#car"/></svg>   mein Auto</li>
	<li><svg><use href="https://example.net/assets/icons.svg#boat"/></svg>  mein Boot</li>
</ul>

Wenn man die Icons zusätzlich zu vorhandem Text einsetzt (was generell eine gute Idee ist), kann man auf progressive enhancement setzen: Wenn die Bilder nicht geladen werden, ist das sollte nicht tragisch; die Icons sind ja „nur“ Zusatz zum Text.

Damit steht der Verwendung von SVG-Icons nichts im Wege. Und es gibt keinen Grund für Icon-Fonts mehr. Keinen!

Empfehlung: Diese Methode hat nur Vorteile:
  • Alle SVG-Icons sind in einer Grafik integriert und benötigen so nur einen HTTP-Request.
  • Diese Grafik-Datei wird nach dem ersten Aufruf im Cache gespeichert.

mehrfarbige, animierte Icons

einheitlicher CSS-Stil

Durch die Möglichkeit die Präsentationsattribute der SVG-Elemente in CSS in Klassen zusammenzufassen, können Sie Multi-Color-Icons mit einem einheitlichen Erscheinungsbild gestalten.

Beispiel ansehen …
<a href="" xlink:href="">
    <desc>Icon für Home-Button</desc>	
    <rect class="background" x="1" y="1" width="59" height="59" />			
    <rect x="10" y="35" width="40" height="24" fill="#ccc" stroke="black" stroke-width="0.5" />
    <rect x="40" y="15" width="5" height="15" fill="black" />
    <path d="M8,35 l22,-20 l22,20 z" fill="#c32e04" stroke="black" stroke-width="0.5" />
    <rect x="15" y="45" width="8" height="14" class="window" stroke="black" stroke-width="0.5" />	  
    <rect x="35" y="45" width="8" height="8" class="window" stroke="black" stroke-width="0.5" />	 
</a>
Die sechs dargestellten Icons zeigen die Möglichkeiten, mit nur wenigen Grundformen mehrfarbige Icons zu kreieren.

S

Empfehlung: Verwenden Sie einen einheitlichen Stil (Skeumorphisches oder Flat-Design) für Ihre Icons - es wirkt ruhiger und stimmiger.

Animationszustände

Die obigen Icons sind interaktiv: Wenn Sie durchtabben oder mit der Maus über die Links fahren, werden :hover und :focus aktiviert.

Beispiel ansehen …
.background {
  fill: none;
}

a:hover .background,
a:focus .background {
  fill: #fffbf0;
  stroke: #e7c157;
  stroke-width:1;
}

.window {
  fill: #666;
}

a:hover .window,
a:focus .window {
 fill: #dfac20;
}
Zur besseren Sichtbarkeit wird bei :hover und :focus ein gelber Hintergrund hinter die Icons gelegt. Im Home-Icon werden die normalerweise dunklen Fenster beleuchtet.
  <a href="" xlink:href="">
      <desc>Icon für Home-Button</desc>	
	  <rect class="background" x="1" y="1" width="59" height="59" />			
          ...
	  <rect x="15" y="45" width="8" height="14" class="window" stroke="black" stroke-width="0.5"/>	  
	  <rect x="35" y="45" width="8" height="8" class="window" stroke="black" stroke-width="0.5"/>	 
  </a>
In SVG ist es nicht möglich, einem Verweis oder einer Gruppierung eine feste Größe und dafür eine Hintergrundfüllung zu geben. Um dies zu erreichen, wird der Grafik ein Rechteck in den gewünschten Dimensionen untergelegt. Normalerweise erhält es keine Füllung - bei :hover und :focus erhält es eine gelbe Füllung, die als Hintergrund für das Icon wirkt.

Siehe auch

Sie können SVG-Sprites auch als Hintergrundbilder in ein Stylesheet einbinden. Dabei könen Sie entweder das SVG-Markup inline ins CSS notieren als auch Teile einer SVG-Grafik über den Fragmentbezeichner (fragment-identifier) identifizieren und referenzieren.

Hauptartikel: SVG/Tutorials/Einstieg/Einbindung#Inline-SVG im CSS

Weblinks

  1. Wikipedia: Sprite (Computergrafik)
  2. SELF-Forum: .png Icon durch .svg ersetzen vom 29.11.2021
  3. CSS-Tricks.com Understanding and Manually Improving SVG Optimization von Raymond Schwarz 18.05.2015
  4. http://demosthenes.info/blog/807/SVG-Optimisation-The-Basics
  5. Wikipedia: Sodipodi
  6. SELF-Forum: Icon, png mit transparenten Hintergrund mittels CSS färben vom 23.08.2018
  7. SELF-Forum: Tutorial vom 24.08.2018


englisch:

Sprite-Generator:

  • github: SVG Sprite
    SVG Sprite is a Node.js module, which optimizes a bunch of SVG files, and bakes them into SVG sprite-types including traditional CSS sprites for background and/or foreground images, SVG stacks and more.

Beispiele

Code-Optimierer

Mittlerweile gibt es mehrere Möglichkeiten, durch Grafik-Programme erstellte SVG-Grafiken nachträglich zu optimieren.

Am sinnvollsten ist die Entfernung der Namespace-Deklarationen und Reduzierung der Dezimalstellen bei Attributen und Stildeklarationen. Leere Elemente und Gruppierungen werden entfernt, sowie Pfade zusammengefasst.

Beachten Sie: Wenn Sie die ids entfernen, werden auch keine Verläufe mehr geladen.
  • SVGOMG von Jake Archibald funktioniert online und hat Einstellungen wie z. B. das Reduzieren von Farben und Entfernen überflüssiger stroke- und fill-Eigenschaften.
    Sie können SVGOMG auch speichern und offline verwenden.
  • SVGO ist ein node-basiertes Kommandozeilenwerkzeug, mit dem Sie ebenfalls SVG-Grafiken aufräumen können.
  • github: SVG Cleaner