SVG-Sprite als Background: Nutzung und Automatisierung

Aus meiner Sicht setzen sich SVG Grafiken so langsam gegenüber Icon-Fonts durch. Der große Vorteil von SVG ist das Browser übergreifend gleiche Rendering, was bei Schriften nicht gewährleistet ist. Die Manipulations- und Animationsmöglichkeiten sind ein weiteres großes Plus.

In diesem Beitrag betrachte ich zunächst einen Workflow für automatisierte SVG-Sprites zur Anwendung als Hintergrund. Im nächsten Artikel geht es dann um SVG-Sprites für die Inline-Nutzung.

Vorbedingungen

Wer noch keinen Schimmer von SVG hat, sollte sich unbedingt vorher bei Chris und Sara in dieses komplexe Themenfeld einlesen.

Auch mit Grunt sollte man schon mal gearbeitet haben.

Einbindungstechniken

Es gibt verschiedenste Ansätze zur Einbindung von Vektor-Grafiken. Als die sinnvollsten betrachte ich zur Zeit folgende:

  1. Reguläres Sprite zur Nutzung im CSS-Hintergrund (background-image)
  2. Symbole in einer extern referenzierten Datei
  3. SVG komplett inline (zur vollständigen Manipulation mit CSS und JavaScript)

Neben der Abbildungsqualität soll durch die Nutzung von SVG natürlich auch die Performance verbessert oder zumindest gleich gehalten werden. Damit dies gelingt sollten SVG-Grafiken – wenn möglich und sinnvoll – auch immer als Sammlung (Sprite oder Symbol-Sammlung) ausgeliefert werden. Das spart HTTP-Requests. Es gibt natürlich auch Use Cases, bei denen eine einzelne Grafik sinnvoll ist, z. B. das Logo einer Website.

Ich gehe bei meiner Beschreibung der Workflows von folgender Struktur des Projektverzeichnisses aus:

root
|-- src
|  |--img
|  |  |--heart.svg
|  |  |--shopping-cart.svg
|  |  |--...
|  |--scss
|--dest

Globales Setup

Ich empfehle für die automatische Sprite-Generierung den npm-Task grunt-svg-sprite für Grunt. Damit ihr das Paket installieren könnt, muss node.js installiert sein.

  1. Wechselt auf der Konsole cmd in das Projektverzeichnis
  2. Stellt sicher, dass dort eine package.json angelegt ist
  3. Installiert grunt-svg-sprite über den Befehl npm install grunt-svg-sprite --save-dev

Reguläres SVG-Sprite zur Nutzung im CSS-Hintergrund

Diese Methode kurz zusammengefasst:

  • Nutzung als background-image: url(sprite.svg);
  • Die Größe des Containers muss dasselbe Seitenverhältnis wie das SVG haben
  • Eine Größenveränderung erfolgt durch Anpassung der background-size
  • Die Sprite-Grafik ist cachebar
  • Die Farben sind nicht einfach manipulierbar

Grunt-Task konfigurieren

Für diese Nutzungsart verwende ich folgende Einstellung im Grunt-Task:

svg_sprite: {
  icons: {
    expand: true,
    cwd: 'src/img',
    src: ['**/*.svg'],
    dest: "./",
    options: {
      mode: {
        css: {
          bust: false,
          dest: "dest/css",
          sprite: "../img/icons.svg",
          mixin: 'icons',
          render: {
            scss: {
              dest: '../../src/scss/_sprite.scss',
              template: 'src/scss/sprite.mustache'
            }
          }
        }
      }
    }
  }
}

Als globalen Destination-Folder gebe ich mit ./ den Verweis zum Verzeichnis der Gruntfile.js an, damit der Task die zusammengefügten SVGs und die SCSS in unterschiedlichen Ordnern ablegen kann.

Neben dem mode verfügt der Grunt-Task noch über viele weitere Optionen, die aber für unsere Zwecke erstmal nicht benötigt werden. Mindestens ein mode muss angegeben werden, damit der Task funktioniert. In diesem Fall generiert uns der Modus css ein gewöhnliches Sprite, wie wir es aus Zeiten mit PNG-Grafiken kennen. Dieses wird dann in dest/img/icons.svg generiert.

Zusätzlich zum Sprite erhalten wir CSS oder SCSS Code, der vorgefertigte Klassen oder Mixins enthält, die man zur Anzeige der SVGs nutzen kann. Der Speicherort wird in der Option render.scss.dest festgelegt und ist relativ zum dest-Verzeichnis des Modus zu sehen.

SCSS-Ausgabe manipulieren

Der SCSS-Code, den man standardmäßig erhält, ist leider unzureichend, wenn man damit effizient weiterarbeiten möchte. Die Angabe der background-size fehlt z. B. gänzlich, was die Skalierung der Grafiken unmöglich macht. Abhilfe schafft hier das individuelle Template, welches man in Form eines mustache-Templates angeben kann. Im Template hat man Zugriff auf alle nötigen Werte der SVG-Grafiken. Mein mustache-Template sieht so aus:

$icons: (
  {{#shapes}}
  "{{name}}": (
      x: {{position.relative.x}}%,
      y: {{position.relative.y}}%,
      width: {{width.outer}},
      height: {{height.outer}}
  ){{^last}},{{/last}}
  {{/shapes}}
);

@mixin icon($name, $size: 100){
  $sizeFactor: ($size / 100);
  $targetWidth: {{spriteWidth}} * $sizeFactor;
  $targetHeight: {{spriteHeight}} * $sizeFactor;
  $icon: map-get($icons, $name);

  background: url({{{sprite}}}) no-repeat;
  background-position: map-get($icon, x) map-get($icon, y);
  background-size: rem-calc($targetWidth $targetHeight);
  width: rem-calc(map-get($icon, width) * $sizeFactor);
  height: rem-calc(map-get($icon, height) * $sizeFactor);
}

Dieses Template generiert eine SCSS-Datei, welche eine Map mit allen SVG-Meta-Daten (Position und Größe) und ein Mixin zur Einbindung als Hintergrundgrafik enthält. Als Konvention habe ich alle SVG-Grafiken auf die Breite 100 Pixel normalisiert. So kann durch die Angabe des Size-Parameters eine Breite in Pixeln angegeben werden auf die die Grafik skaliert werden soll. Die errechneten Pixel-Werte werden mit der rem-calc-Funktion von Foundation in die Einheit rem umgewandelt. Dies muss man nicht machen, empfehle ich aber sehr. Die Umrechnung von px nach rem kann aber auch mit einer eigenen Hilfsfunktion geschehen.

SVG-Sprite nutzen

Nach der ganzen Setup-Arbeit wollen wir endlich die Früchte ernten. Dazu muss nur noch die generierte _sprite.scss als Partial in unsere SCSS-Struktur eingebunden werden. So erzielen wir sehr komfortabel die Möglichkeit entsprechende Regeln für die Icons anzulegen.

HTML

<i class="icon icon--heart-30"></i>

SCSS

.icon{
  &:after{
    content: "";
    display: inline-block;
    vertical-align: middle;
  }
}

.icon--heart-30{
  &:after{
    @include icon("heart", 30);
  }
}

Ich nutze hier die BEM-Notation für die Variante des Icons, welches im Textfluss steht. Zuletzt sprechen wir nur noch das Mixin mit dem Namen (abhängig vom ursprünglichen Dateinamen) und der Größe des gewünschten Icons an.

Der Clou wird deutlich, sobald man die nächsten Grafiken in den Ordner wirft und der Grunt-Task optimalerweise per Watcher automatisch ausgeführt wird. Dann muss man nur noch eine Regel duplizieren und den Selektor sowie das include anpassen.

Das initiale Setup kann je nach Projektstruktur ggf. etwas aufwändig sein, die Produktivität steigt aber hinten heraus, wenn man weiß, dass viele SVGs im Projekt genutzt werden. Dieser Workflow ist insgesamt auf jeden Fall schneller als ein Sprite manuell zu pflegen. Auch für die Designer ist es meist einfacher einzelne Grafiken bereitzustellen als ein Sprite zu organisieren. 

Kommentare

  1. Inline-SVG als Sprite: Nutzung und Automatisierung | DESIGNERZONE.DE

    […] Artikel ist als Fortführung von SVG-Sprite als Background: Nutzung und Automatisierung anzusehen. Es gelten dieselben Vorbedingungen und dasselbe […]

    Antworten

Kommentar abgeben

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.