Wahrscheinlich kein Base64 für SVG

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Vielleicht haben Sie schon von Data-URIs gehört. Es ist eine wirklich nette Methode, eine Ressource einzubinden, die sonst eine separate HTTP-Anfrage gewesen wäre. Das Format, das Sie in einem Data-URI verwenden, kann variieren. Im Wesentlichen geben Sie nur den Inhaltstyp an (z. B. image/png), ein Semikolon und dann die Daten dieser Datei.

Wie

<img src='data: ... '>

oder

.bg {
  background: url('data: ... ');
}

Bei einem Rasterbild wie einem PNG müssen die Daten dieses Bildes im Base64-Format vorliegen. Ich bin kein großer Experte, aber soweit ich das verstehe, ist Base64 sicher für die Verwendung in HTML oder CSS, da es nur 64 Zeichen verwendet, die in diesen Formaten als sicher gelten.

Links die Daten eines PNG, die Zeichen enthalten, die HTML durcheinanderbringen können. Rechts dasselbe Bild Base64-kodiert mit allen sicheren Zeichen.

Wahrscheinlich bessere Stack Overflow Antwort von Dave Markle

Man weiß nie – einige Protokolle interpretieren Ihre Binärdaten möglicherweise als Steuerzeichen (wie ein Modem), oder Ihre Binärdaten könnten beschädigt werden, weil das zugrunde liegende Protokoll glaubt, Sie hätten eine spezielle Zeichenkombination eingegeben (wie FTP Zeilenenden übersetzt).

Um dies zu umgehen, kodieren die Leute die Binärdaten in Zeichen. Base64 ist eine dieser Kodierungsarten.

Base64 sieht aus wie Kauderwelsch, und wir assoziieren Kauderwelsch oft mit Kompression im Web. Aber dieses Kauderwelsch ist keine Kompression, es ist tatsächlich etwas größer als das Original, denn um Jon Skeet im selben Stack Overflow Thread zu zitieren:

Es werden 4 Zeichen für je 3 Bytes Daten benötigt, plus möglicherweise etwas Padding am Ende.

Ich bin mir aber nicht sicher, wie Gzip hier einbezogen wird. Aber worauf ich hinauswill, ist, wie SVG hier einbezogen wird.

Sie können Data-URIs auch für SVG verwenden.

<img src='data:image/svg+xml; ... '>
.bg {
  background: url('data:image/svg+xml; ... ');
}

Bei SVG müssen Sie die Daten nicht unbedingt in Base64 konvertieren. Wiederum, ich bin kein Experte, aber ich glaube, die SVG-Syntax enthält einfach keine verrückten Zeichen. Es ist einfach XML, genau wie HTML, also ist es sicher in HTML zu verwenden.

Sie können die Kodierung in UTF-8 belassen und die <svg>-Syntax direkt einfügen! So:

<img src='data:image/svg+xml;utf8,<svg ... > ... </svg>'>
.bg {
  background: url('data:image/svg+xml;utf8,<svg ...> ... </svg>');
}

Da wir das tun können und wissen, dass Base64 oft die Größe erhöht, ist es dann nicht gleich gut, das zu tun? Ja. Als Nebeneffekt komprimiert die unveränderte <svg>-Syntax besser, da sie weitaus repetitiver ist als Base64. Nehmen wir an, Sie möchten zwei Versionen eines Icons, eine rote, eine gelbe. Sie können die gleiche SVG-Syntax duplizieren und nur die Füllfarbe ändern. Gzip wird das im Handumdrehen verarbeiten. Dank an Todd Parker für diesen Tipp, und das ist auch der Ansatz von Grunticon, das SVG in UTF-8 in CSS mit Data-URIs einbettet.

Ein Test

Um dies auszuprobieren, habe ich drei SVG-Icons von IcoMoon heruntergeladen.

cog.svg – 1.026 Bytes
play.svg – 399 Bytes
replay.svg – 495 Bytes

Ich habe sie durch SVGO laufen lassen, damit sie schön optimiert und quasi bereit für die Verwendung als Data-URI sind (Leerzeichen entfernt, obwohl das nicht unbedingt notwendig ist).

cog.svg – 685 Bytes
play.svg – 118 Bytes
replay.svg – 212 Bytes

Dann habe ich diese durch einen Base64-Konverter laufen lassen.

cog.svg – 916 Bytes – 133% der Originalgröße
play.svg – 160 Bytes – 136% der Originalgröße
replay.svg – 283 Bytes – 134% der Originalgröße

Das macht Sinn, oder? Wenn es 4 Zeichen für je 3 Bytes sind, ist das 133% größer, wobei die Abweichung von ungleichmäßigen Längen und damit Padding herrührt.

Nun, vielleicht ist das alles offensichtlich. Aber mir scheint, wenn man einen Data-URI für SVG verwenden möchte, gibt es keinen Grund, ihn jemals mit Base64 zu kodieren.

Ein Dank an Matt Flaschen für seine E-Mail vor ein paar Monaten, die mich auf dieses Problem aufmerksam gemacht hat.

UPDATE: zu IE

In den Kommentaren wird viel über IE 10/11/Edge gesprochen, die das nicht unterstützen. Das stimmt nicht, es ist nur wählerisch. Hier ist ein reduzierter Testfall, der in diesen IE-Versionen funktioniert. Beachten Sie, dass das zweite Beispiel, das URL-kodiert ist, funktioniert. Der Trick ist, überhaupt keinen Encoding-Typ anzugeben.

UPDATE: „Optimiert URL-kodiert“

Taylor Hunt hat etwas tiefer recherchiert und herausgefunden, dass Sie noch etwas mehr Optimierung herausholen können, indem Sie Dinge wie Leerzeichen und einfache Anführungszeichen nicht kodieren. Beispiel:

data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M224%20387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.93 0 521.287 151.707 491.48 394.785 224 387.814z'/%3E%3C/svg%3E