SVGs können nicht nur mit Grafikprogrammen wie Adobe Illustrator oder Inkscape erstellt werden, sondern auch mit einem einfachen Texteditor – oder programmatisch mit jeder Skriptsprache, die man so zur Hand hat. Damit die SVG-Grafik aber in jedem Umfeld funktioniert, sind ein paar Besonderheiten zu beachten:

Struktur

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" viewBox="0 0 100 100" width="210mm" height="210mm" xmlns="http://www.w3.org/2000/svg">
  <title><!-- Document Title goes here --></title>
  <style>
    <!-- CSS goes here -->
  </style>
  <defs>
    <!-- Optional: Pastable objects -->
  </defs>
  <!-- Here comes the actual SVG -->
</svg>

Die Grundstruktur eines SVG-Dokuments kann man sich ähnlich wie die eines HTML-Dokuments vorstellen:

Zuerst kommen Meta-Angaben. Dazu gehört der Dokumenten-Titel, CSS und gegebenenfalls noch <defs>, falls ihr Grafikkomponenten mehrfach verwenden wollt.

Erst danach sollte die eigentliche Ausgabe von Grafikelementen beginnen.

Title

In SVG hat das <title>-Tag mehrere Bedeutungen:

  1. Wenn es auf der obersten Ebene steht wird es wie das <title>-Tag HTML verwendet, um den Namen eines Dokuments festzulegen.
  2. Wenn es innerhalb des Dokuments vorkommt übernimmt es die Funktion des aus HTML bekannten title-Attributs. Beim Überfahren mit der Maus wird zum Beispiel eine kleiner Tooltip angezeigt.

CSS

…funktioniert wie in HTML. Dementsprechend sollte man versuchen, nicht jedem Element einzeln mittels stroke- und fill-Attributen Styles zuzuordnen, sondern mit CSS das Layout globaler zu definieren.

Tatsächlich gibt es aber ein paar Besonderheiten bei der Verwendung von CSS in SVGs:

RGBA-Farben funktionieren nicht zuverlässig

RGBA-Farben haben die Fähigkeit, darunterliegende Teile einer Grafik durchscheinen zu lassen. Der Alpha-Kanal bestimmt dabei die Durchlässigkeit bzw. Opazität. Leider werden RGBA-Farben nicht in jedem Fall korrekt ausgegeben. Die meisten Browser können es, dafür kaum ein Grafikprogramm oder Bildbetrachter.

Stattdessen gibt es verschiedene Formen von Opazität bzw. Transparenz.

  • opacity macht ein gesamtes Element,
  • fill-opacity nur die Füllung,
  • stroke-opacity nur die Umrandung opak bzw. transparent.

In CSS sieht das wie folgt aus:

.black-a-fifty {
  /* fill: rgba(0,0,0,0.5); --- will not always work */
  fill: #000000;
  fill-opacity: 0.5;
}

CSS Custom Properties funktionieren nicht zuverlässig

Fans von CSS Custom Properties haben bei SVG ebenfalls kein Glück: Die meisten Grafikprogramme können diese Variablen nicht verarbeiten. Stattdessen gibt es aber einen kleinen Ausweg mit dem CSS-Wert currentColor:

Der Wert für currentColor wird mit der in SVG sonst irrelevanten CSS-Eigenschaft color gesetzt (die im Gegensatz zu der gleichnamigen Eigenschaft in HTML nicht aktiv ELemente einfärbt – dafür ist in SVG ja fill und stroke da). Der Aufruf von currentColor wird dann mit dem zuletzt via color gesetztem Wert gefüllt – ganz wie bei einer CSS Custom Property.

.black {
  color: black; /* sets currentColor to `black` */
}

.red {
  color: red; /* sets currentColor `red` */
}

/* These elements will be colored black or red, depending on class */

rect {
  stroke: currentColor;
  fill: currentColor;
}

text {
  fill: currentColor;
}

Mehrzeiliger Text

In SVG kann in Theorie nur einzeiliger Text gesetzt werden, beziehungsweise muss jede neue Zeile neu positioniert werden. Mit einem kleinen Trick kann man aber mehrzeiligen Text erstellen, indem jede Zeile in ein <tspan>-Element gehüllt und diese relativ unter der vorhergehenden Zeile positioniert wird:

<text>
  <tspan x="0">Line 1</tspan>
  <tspan x="0" dy="1.1em">Line 2</tspan>
  <tspan x="0" dy="1.1em">Line 3</tspan>
  <tspan x="0" dy="1.1em">Line 4</tspan>
</text>

Wichtig ist hier die Definition des Zeilenabstands – diese muss in jedem dy-Attribut wiederholt werden.

Wenn ihr Links in eurem SVG verwenden wollt, gibt es zwei Wege, wobei je nach Ausgabemedium nur einer von beiden funktioniert… oder auch gar keiner.

Die veraltete, aber noch weit verbreitete Methode sind xlink:href-Attribute, die die Ziel-URL an einem Element festlegen. Damit diese funktionieren, muss zuerst an dem <svg>-Knoten ein neuer Namespace deklariert werden:

<svgxmlns:xlink="http://www.w3.org/1999/xlink">

Sobald dieser Namespace bekannt ist, kann das Attribut verwendet werden.

In SVG2 wird stattdessen das aus HTML bekannte <a>-Tag mit href-Attribut verwendet.

Für eine maximale Kompatibilität kann man beide Techniken miteinander kombinieren:

<a xlink:href="https://www.example.com" href="https://www.example.com">…</a>

Übrigens: Die Links für <defs> und <use> werden mit dem selben xlink:href- beziehungsweise href-Attribut gebaut.

Linien abrunden

Im Standard sind SVG-Linien eine scharfkantige Sache. Zum Glück gibt es CSS-Eigenschaften, die sowohl die Enden mit stroke-linecap als auch die Ecken mit stroke-linejoin abrunden können.

.rounded-line {
  stroke-linecap: round;
  stroke-linejoin: round;
}

Inkscape

Wenn euer SVG-Dokument auch in Inkscape bearbeitbar sein soll, könnt ihr mit einem zusätzlichen XML-Namensraum kleine Helferlein im Dokument hinterlassen:

<svgxmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">

Jetzt steht euch die Möglichkeit zur Verfügung, die aus Inkscape bekannten Layer in eurem SVG zu verwenden. Dazu müsst ihr eine beliebige Gruppe nur mit zusätzlichen Attributen ausstatten:

<g inkscape:groupmode="layer" inkscape:label="Name your layer">…</g>

Fazit

Wenn eure SVGs nicht nur in modernsten Browsern, sondern auch in älteren Browsern und Grafikprogrammen funktionieren soll, müssen ein paar Spielregeln eingehalten werden. Im Endeffekt ist nach kurzer Umgewöhnung das Erzeugen wunderschöner SVG-Dokumente nicht viel komplizierter als das Erstellen von HTML-Dokumenten.