SVG, yeah you know me

Update: Der hier besprochene Bug wurde inzwischen gefixt.

Oder eher I know you. Über den meiner Meinung nach vorliegenden Safari SVG Sprite Bug hatte ich ja schon berichtet. Kurz zusammengefasst: neuere (mobile) Safari laden ein SVG-Sprite jedesmal komplett runter, wenn ein SVG-Icon daraus angezeigt wird. Das konnten beim ersten Aufruf ohne gefülltem Cache bei der Homepage von zeit.de schon mal bis zu 17MB sein. Um es kurz zu machen, die Welt interessiert sich nicht dafür, weder Apple, die den Safari baut, und auch nicht die Autoren von svg4everybody, die die SVG-Sprite-Technik populär gemacht haben (unter Webentwicklern).

Update: Martin Wolf hat den Screencast zum Bug gedreht.

Lösungssuche

Also mussten wir anderweitig handeln und die Sprites ersetzen. Wenn man nun einmal SVG eingeführt hat, will man nicht wieder zurück auf Pixelbilder umsteigen. Ich habe also lange recherchiert, nach Techniken gesucht, versucht das Problem irgendwie wegzubekommen, allerdings ohne Erfolg. Eine Idee war, und die halte ich durchaus für valide, die SVG per XHR in die Seite zu laden. Für uns sprachen jedoch zwei entscheidende Dinge dagegen:

  • progressive enhancement: es gibt in dem Sinne keine wirkliche Basis, von der die AJAX-Lösung enhancen könnte, ausser vielleicht man schreibt einen Text anstelle des SVG und lädt an dieser Stelle dann die Grafik hinein. Grafik und Text nehmen aber nur selten den gleichen Raum ein, ein fürchterliches Geruckel und Gezucke wäre vorprogrammiert, überall dort, wo der Text größer als die Grafik wäre
  • unsere großen und komplizierten Logos: die Signets der ZEIT, des ZEIT MAGAZIN und so fort sind auch nach vielen Optimierungen immer noch sehr große SVG-Dateien mit vielen Knotenpunkten, gerade diese sollten aber immer vorhanden sein, dürfen also nicht durch Text ersetzt und per XHR nachgeladen werden. D.h. für die Logos musste sowieso eine andere Lösung gefunden werden (die noch verbleibenden Icons sind dann schon fast unerheblich klein).

Für die Logos war schnell klar, dass wir diese oldschool in das HTML einbetten müssen, so wie es auch bspw. Github mit seinen Icons macht. Am Ende haben wir uns entschieden, es mit allen Icons so zu machen: wir betten sie ins HTML ein.

<svg xmlns="http://www.w3.org/2000/svg" width="17" height="15" viewBox="0 0 17 15" class="svg-symbol" preserveAspectRatio="xMinYMin meet" role="img" aria-label="Leserempfehlung">
    <path d="M8.5 11.454L3.322 15l1.983-5.73L.12 5.73l6.405.004L8.5 0l1.975 5.734 6.404-.005-5.185 3.54L13.678 15"></path>
</svg>

Nach- und Vorteile

Das birgt tatsächlich ein paar Nachteile, vor allem weil die Grafiken damit zu Textcontent werden, zumindest aus Sicht des Cachings, es wird also nahezu nicht gecached. Das SVG-Sprite, dass nun wegfällt hingegen wurde natürlich auf ewig gespeichert. So wiegt die Seite nur beim initialen Laden weniger als vorher. Das ist leider weitestgehend ungelöst, auch wenn ich die Hoffnung habe, dass sich die SVG wenigstens sehr gut gzippen. Es bleibt aber eine lästige Abhängigkeit, die man eigentlich nicht haben will. Ohne Zweifel ist der Gewinn für Nutzer des mobile Safari allerdings grandios.

Die Lösung bringt aber auch Vorteile. Zunächst mal können wir uns nun eine Sonderlösung für cross-domain-Seiten einsparen und haben eine Menge polyfills abgeschafft, da das inlinen von SVG eine hervorragende Browserunterstützung genießt. Unser Grunt-Workflow hat sich dadurch auch deutlich verschlankt, weil wir bspw. keine Fallback-Bilder im PNG-Format mehr produzieren. Für das Einlesen der SVG habe ich einen Jinja-Helper geschrieben, der die Daten von der Platte holt (und das Ergebnis wegcached), und noch ein paar Änderungen am Code vornimmt, die wir sonst im Grunt mit svgstore gemacht haben (bspw. fill-Attribute wegstrippen). Außerdem kann man beim Aufruf das Füllen der ARIA-Attribute beeinflussen, damit in Situationen, in denen das Icon direkt neben einem erklärenden Text steht, kein doppeltes Vorlesen passiert:

<a href="#leserempfehlung">
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="15" viewBox="0 0 17 15" class="svg-symbol" preserveAspectRatio="xMinYMin meet" role="img" aria-hidden="true">
    <path d="M8.5 11.454L3.322 15l1.983-5.73L.12 5.73l6.405.004L8.5 0l1.975 5.734 6.404-.005-5.185 3.54L13.678 15"></path>
</svg>
Leserempfehlung
</a>

Zumindest wurde so der Prozess auf Entwicklerseite stark vereinfacht. Und ein paar nodige Abhängigkeiten entfernt.

Geschmäckle

Was bleibt ist die Frage, warum das Problem eigentlich niemanden so richtig interessiert. Zunächst mal nehme ich inzwischen an, dass wir als Hochlastwebsite mit Massencontent zu den Paradiesvögeln gehören, wenn wir moderne Techniken des Web einsetzen. Die Verbreitung einer Lösung wie SVG-Sprites und da kann Chris Coyier noch auf sovielen Konferenzen dafür Werbung machen, scheint vergleichsweise gering, jedenfalls auf Seiten, die vielleicht mehr als ein oder zwei Icons pro Seite haben. Und dann interessiert es die Betreiber der Seiten, die das nun doch nutzen vielleicht auch nicht richtig, wieviel Megabytes für iPhone-Nutzer durch den Äther gejagt werden. Vielleicht monitoren sie das auch nicht so. Der Kunde merkt es vielleicht auch nur, wenn die sogenannte Flatrate schon Mitte des Monats leergesaugt ist. Apples Verhältnis zu Safari scheint sowieso ein Gebrochenes zu sein, was sich widerum im Verhältnis von Safari zu aktuellen Webtechnologien zeigt, da wird sogar zurückgebaut! Und schlussendlich muss ich auch zugeben, wahrscheinlich haben wir es mit unserem Sprite von der Größe her ein wenig übertrieben, zumindest hat das dem Bug vorschub geleistet.

4 Antworten auf „SVG, yeah you know me“

  1. Hallo Nico,

    ich habe bis gestern überhaupt nichts von diesem Bug mitbekommen. Dein initialer Beitrag ist vollkommen an mir vorbeigegangen, weil ich Anfang des Monats kaum in Twitter war. Ein Beitrag auf einer publikumsstarken Webseite wäre da hilfreich.

    Zudem gehöre ich noch zu den SVG-Verweigerern. Und just als ich dachte, ein SVG-Sprite sei vielleicht doch nicht so doof, da kommst Du mit dieser Erkenntnis um die Ecke. Das ist schon blöd. Blöd ist auch, dass es Apple betrifft. Bei jedem anderen Hersteller gäbe es jetzt einen Fix. Bei Apple wird es noch ewig dauern. Die sind eine große Enttäuschung auf ganzer Linie.

  2. Also, dass das Problem niemanden interessiert muss ich schon mal revidieren. Seit gestern wird darüber auf Twitter und an anderen Stellen inzwischen fleissig diskutiert.

  3. Ich bin vorgestern etwas erschrocken, als ich in Jens Blog den Beitrag dazu gesehen habe. Wir setzen seit einiger Zeit ausschließlich auf SVG-Sprites. Die SVG-Sprites werden aber anders als bei zeit.de ganz ordinär als Hintergrundbilder von Pseudo-Elementen eingebunden und nicht als SVG external content. Das bringt im Vergleich ein paar Nachteile mit sich und ist von Bitmap-Sprites ausgehend eher ein evolutionärer als revolutionärer Schritt. Dafür ist es recht simpel möglich ein Bitmap-Fallback zu integrieren, wenn das PNG-Sprite aus dem SVG-Sprite heraus generiert wird.

    Der Bug macht sich dann nicht bemerkbar. Das SVG wird lediglich einmal geladen (Mac Safari 9.1, für 9.0 will ich meine Hand jetzt nicht ins Feuer legen ;)).

    Deine Ausführungen und die Reaktionen lassen unberücksichtigt, dass der Bug, der wirklich unschön ist, dass das Problem unter bestimmten Voraussetzungen auftritt: SVG external content. SVGs und SVG-Sprites als solche zu verdammen schiesst deutlich darüber hinaus.

  4. Deine Ausführungen und die Reaktionen lassen unberücksichtigt, dass der Bug, der wirklich unschön ist, dass das Problem unter bestimmten Voraussetzungen auftritt: SVG external content.

    Nein, überhaupt nicht, im verlinkten Artikel über den Bug ist klar dargestellt, inkl. Code, dass es um external SVG-Sprites geht. Und das es auch nur um Safari geht.

    SVGs und SVG-Sprites als solche zu verdammen schiesst deutlich darüber hinaus.

    Das will auch niemand.

    Ich wüsste nicht, wo wir ohne SVG und die oben skizzierte Sprite-Lösung gehör(t)en zu den wirklich wichtigen Workflows mit denen wir eine responsive Website überhaupt erst ermöglichen können, ohne gleich Gigabytes Bilddaten durchs Netz zu schaufeln. Und genauso schwer hat uns der Bug betroffen.

    Es handelt sich aber ja nicht um eine Linux vs. Windows Streiterei, es gibt wirklich keine bessere Lösung zur Zeit. Natürlich kann ein Bug mal vorkommen, aber… und hier setzt meine Kritik am Ökosystem Web ein, wie lange wird es dauern (er ist inzwischen bei Webkit anerkannt, gepatched und gefixt), bis ein Fix landet in iOS? Und wenn es viele Seiten gibt, die den Bug haben und es vielleicht gar nicht merken, dann zahlt am Ende der Nutzer dafür, im Zweifel mit einer frühzeitig ablaufenden sog. Flatrate.

Kommentare sind geschlossen.