von Andy Pillip
SVGs im Web praktisch einsetzen
Ein Experiment zu flexiblen SV-Grafiken in HTML für Responsive Design
Verwenden Sie SVG noch heute, die Zeit ist reif
Auf diesen Aufruf bin ich bei meinen Recherchen mehrmals gestoßen. Doch in unserem letzten Projekt mit Anspruch auf gnadenlos scharfe Grafiken auch auf HD-Bildschirmen (Apple nennt sie Retina) stellt sich die Realität anders dar.
Ich habe ein kleines HTML-Experiment aufgebaut, um mir das mal genauer anzuschauen. Auf Lösungen mit JavaScript gehe ich hier nicht ein. Weiter unten findet sich eine zusammenfassende Tabelle der Testergebnisse.
Prinzipielle Browserunterstützung
Ein Blick auf Can I use SVG bringt zunächst nichts überraschendes: Internet Explorer versteht das Format erst ab Version 9, die üblichen Verdächtigen hatten schon immer Unterstützung für SVG.
Erstaunlich ist allerdings, dass gerade Google, die das Format SVG und Performance extrem bewerben, in die frühen Android-Browser (bis einschließlich Android 2.3) keine Unterstützung eingebaut haben. Und der Marktanteil dieser Browser(versionen) ist noch enorm.
SVG in HTML einbetten: die verschiedenen Elemente
In Frage kommen (neben JavaScript-Lösungen) das object-, das (jetzt wieder erlaubte) embed-, das img- und das svg-Element, die ich im Experiment getestet habe.
object
Dieses Element ist am vielversprechendsten, weil es eine lange Geschichte hat und einen ordentlichen Fallback bietet: Wird das zu ladenende Format nicht unterstützt, lässt sich mit HTML strukturiert eine Alternative angeben.
<object type="text/svg+xml" data="test.svg" width="100" height="100">
<p>Hier
lässt sich strukturiert eine Alternative beschreiben</p>
<p>Oder einfach
nur das wenig hilfreiche: Ihr Browser unterstützt kein SVG</p>
</object>
Die strukturierte Alternative macht theoretisch das object-Element sogar für normale Bilder attraktiver als das img-Element.
embed
Eigentlich ist es gar kein HTML-Element, wurde aber mit HTML5 wieder erlaubt, nachdem es viel für das Einbinden von Flash verwendet wurde.
Der Unterschied zum object-Element ist, dass man eine URL zum Herunterladen des richtigen Plugins angeben kann — aber keine Alternative.
<embed type="image/svg+xml" src="test.svg" />
img
Das gute alte Element zum Einbinden von Grafiken. Es wird erst mal als inline-Element dargestellt, bleibt also im Textfluss.
<img src="test.svg" width="100" height="100" alt=""/>
svg
Dieses Element ist erst mit HTML 5 hinzu gekommen, und referenziert die SVG-Datei nicht, sondern erwartet deren Quellcode direkt im HTML. Dadurch sind auch die Grafikelemente der SVG direkt im DOM-Baum und man hat den Vorteil, dass man in JavaScript uneingeschränkt Zugriff auf die SVG-Elemente hat und diese beeinflussen kann.
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g fill="#fff">
…
</svg>
background-image (CSS)
Man kann natürlich auch in CSS statt in HTML die SVG-Datei zuweisen. Der Haken dabei ist, dass man das HTML-Element nicht mehr ohne weiteres im Verhältnis wachsen lassen kann — es sei denn man bedient sich eines Platzhalterbildes, das das Verhältnis beim Vergrößern einhält. Und man braucht auf jeden Fall irgendwo Text als Fallback.
#svg {
background: url("test.svg") no-repeat left top;
background-size:
100% auto;
}
Flexible Bilder (responsive images)
Natürlich ist genau so Anspruch, dass sich die Grafiken im Verhältnis an die gewünschte Größe anpassen. Ich brauche nicht von HD-Bildschirmen sprechen, wenn sich meine Grafiken nicht anpassen können, um auch auf Smartphones passend dargestellt zu werden.
Dieses Stückchen CSS sorgt für diese Anpassung im Experiment:
object, svg, img {
display: block;
width: 100%;
height: auto;
}
Skalierbares SVG
SV-Grafiken verändern sich aber gar nicht in der Größe, wenn nicht bestimmte Angaben im svg-Element in der Datei gemacht werden.
Es braucht alle Attribute preserveAspectRatio="xMinYMin meet" width="100"
height="100" viewbox="0 0 100 100"
, damit alle Browser damit umgehen können.
Verlinkte Vektorgrafiken
Vektorgrafiken machen besonders für Symbole, zum Beispiel auf Symbolleisten, Sinn. Genau dort ist ihre Aufgabe aber, zur Interaktion zu motivieren.
Also müssen die Grafiken auch verlinkbar sein, also in ein a-Element gepackt werden können. Zur besseren Darstellung habe ich im Experiment diesem Element einen schwarzen Rahmen gegeben.
Testgeräte und -browser
Für meinen kleinen Test hier hatte ich zur Verfügung:
- iPad 3 mit Safari, Chrome 21 und Dolphin
- Samsung Galaxy Tab mit Android 2.2.1, Firefox 17 und Opera mobile 12.10
- Samsung Galaxy S3 mit Android 4.1.1, Firefox 17, Opera mobile 12.10 und Chrome 18.0
- Ubuntu 12.04 mit Firefox 17, Chromium 20.0, Opera 12.11
Die Testseite
Auf meiner Testseite hat der body nicht die volle Breite, um die Skalierbarkeit erfassbar zu machen. Die Links haben einen schwarzen Rahmen, damit man sie erkennt.
Und zuerst gebe ich den User-Agent Inhalt aus, um die Browserversion dokumentieren zu können.
Testergebnisse
Browser und Plattform | object | img | svg | background-image mit platzhalterbild |
---|---|---|---|---|
Webkit
|
||||
Chromium 20/Ubuntu 12.04 | falsche Größe, nicht verlinkbar | ok | falsche Größe | ok |
Chrome 18/Android 4.4.1 | bisserl abgeschnitten, nicht verlinkbar | ok | horizontal Leerraum | ok |
Chrome 21/iPad 3 | abgeschnitten, nicht verlinkbar | zu breit | nicht unterstützt | ok |
Safari/iPad 3 | abgeschnitten, nicht verlinkbar | zu breit | nicht unterstützt | ok |
Android Browser 2.2.1 | SVG wird nicht unterstützt | SVG wird nicht unterstützt | SVG wird nicht unterstützt | SVG wird nicht unterstützt |
Android Browser 4.4.1 | abgeschnitten, nicht verlinkbar | zu hoch | nicht unterstützt | ok |
Gecko | ||||
Firefox 17/Android 2.2.1 | nicht verlinkbar | ok | ok | ok |
Firefox 17/Android 4.4.1 | nicht verlinkbar | ok | ok | ok |
Firefox 17/Ubuntu 12.04 | nicht verlinkbar | ok | ok | ok |
Firefox 10 ESR/Windows 7 | nicht verlinkbar | ok | ok | ok |
Presto | ||||
Opera mobile 12.10/Android 2.2.1 | unscharf, nicht verlinkbar | unscharf | unscharf | unscharf |
Opera mobile 12.10/Android 4.4.1 | unscharf, nicht verlinkbar | unscharf | unscharf | unscharf |
Opera 12.11/Ubuntu 12.04 | nicht verlinkbar | ok | ok | unscharf |
Dolphin Browser/iPad 3 | abgeschnitten, nicht verlinkbar | zu breit | nicht unterstützt | ok |
Trident | ||||
IE 8/Windows 7 | nicht unterstützt | nicht unterstützt | nicht unterstützt | nicht unterstützt |
IE 9/Windows 7 | ok | ok | falsche Größe | falsche Größe |
IE 10/Windows 8 | ok | ok | falsche Größe | falsche Größe |
Fehlerhafte Skalierung
Völlig verwirrt war ich von einigen Browsern, zunächst im Safari auf dem iPad 3, die mir zwar die eigentliche Grafik in der richtigen Größe angezeigt haben, aber wahnsinnig viel Platz um die Grafik herum reserviert haben — und zwar immer unterschiedlich viel Platz. Mit wahnsinnig viel meine ich 3-Minuten-nach-unten-scroll viel.
Die Analyse der SVG-Datei hat mir dann gezeigt, dass die Angabe von width und height unbedingt nötig ist, damit die Grafik ordentlich skaliert. Andere Browser (Chromium) brauchen unbedingt die viewBox und das preserveAspectRatio.
Also müssen in der SVG-Datei unbedingt alle drei Angaben vorhanden sein. Nur Firefox und Opera können auch ohne richtig skalieren.
Verlinkbarkeit
Wichtig war, dass sich die SV-Grafik verlinken lässt. Dabei kann nur der Internet Explorer das object-Element verlinken.
img zu verlinken funktioniert bei allen Browsern ohne Probleme.
Leerraum
Webkit-Browser (Chromium, Chrome und Safari) präsentieren die Grafik im SVG-Element mit ordentlich Freiraum in der Vertikalen. Im object-Element existiert dieser Platz auch, aber das Element an sich hat die angegebene Größe.
Letzteres führt dazu, dass bei preserveAspectRatio="XMidYMid"
die
eigentliche Grafik abgeschnitten präsentiert wird. Am Touchscreen lässt sie sich wieder
in die Mitte ziehen.
Unscharfe SVGs
SV-Grafiken sehen theoretisch auf jedem Bildschirm — oder auf Kinoleinwand — so scharf aus, wie es die Hardware erlaubt. Es handelt sich ja um Vektoren, nicht um pixelgenaue Angaben.
Opera mobile bringt aber eine Überraschung: Egal mit welchem HTML-Element die Grafik eingebettet ist, der Browser macht eine Pixelgrafik daraus, was die Grafik unscharf aussehen lässt. Zoomt man näher hin, sieht das katastrophal aus.
In Opera am Desktop sieht die Grafik zumindest per CSS eingebunden scharf aus.
Chrome auf Android macht aus dem SVG im img-Element eine unscharfe Pixelgrafik — und per CSS eingebaut sieht sie sogar noch schlimmer als das im img aus. Am Chrome auf dem iPad ist alles scharf.