Webfonts als Data-URL einbinden

Die übliche Methode zur Einbindung von Webfonts ist die Angabe einer URL zur Datei mit dem jeweiligen Schriftschnitt. Siehe dazu auch meinen älteren Beitrag zu Webfonts.

In der Praxis funktioniert das zwar, aber es gibt durchaus Nachteile bei dieser Methode, besonders wenn mehrere Schriftschnitte verwendet werden.

Das Problem mit vielen HTTP-Anfragen

Ein erheblicher Faktor dafür, wie lange das Laden einer Website dauert, ist neben der Datenmenge die Zahl der erforderlichen HTTP-Anfragen. Jede Anfrage verursacht eine zusätzliche Verzögerung, die auch mit schnellen Verbindungen kaum verringert werden kann.

Jeder eingebundene Webfont muss über eine zusätzliche Anfrage vom Browser aktiv angefordert werden. Bereits bei einer einzigen Schrift mit vier Schnitten sind also mindestens vier weitere Anfragen nötig.

Geht man davon aus, dass die Durchführung einer HTTP-Anfrage etwa 100 ms beansprucht, hat man im Extremfall 400 ms zusätzlichen Zeitbedarf zuzüglich der Zeit für die eigentliche Datenübertragung, bis der Ladevorgang abgeschlossen ist. In der Regel werden Anfragen aber von allen gängigen Browsern parallelisiert, so dass meist 3 oder 4 Zugriffe gleichzeitig erfolgen – dennoch bleiben dann immer noch 100-200 ms zusätzlich, da das Laden der Schriften erst dann beginnt, wenn der Browser das Stylesheet geladen hat und die Angaben darin zum Nachladen der Schriften interpretiert hat.

Ein Beispiel:

Ich verwende auf meiner Website die Schrift „Lato“ in vier Schnitten. Diese Schrift benötigt insgesamt 182 KiB, verteilt auf vier Dateien.

Geht man von einer Übertragungsgeschwindigkeit von 500 KiB pro Sekunde aus, was bereits mit DSL 6000 oder einer guten UMTS/LTE-Verbindung durchaus realistisch ist, erfordert die reine Übertragung dieser Datenmenge rechnerisch 364 ms. Nun kommt noch der Zeitbedarf für die HTTP-Anfragen dazu, was mindestens weitere 200-400 ms bedeutet. Das bedeutet, dass allein das Anfordern der Schriften vom Server fast genauso lang oder gar länger dauert, als die eigentliche Übertragung der Daten. In Kombination mit HTTPS sieht das Ergebnis noch schlechter aus, da hier mehr Zeit für den Verbindungsaufbau benötigt wird.

Man könnte nun in Frage stellen, ob eine halbe Sekunde Ladezeit mehr oder weniger wirklich so entscheidend sind. In der Praxis sind aber nicht alle HTTP-Anfragen immer so schnell, wie es die reine Verbindungsgeschwindigkeit erlauben würde. Es gibt je nach Browser noch ein weiteres Problem, das besonders bei langsamen Verbindungen deutlich wird (z.B. bei mobilen Geräten mit eingeschränkter Netzverbindung): der Browser lädt das Dokument und das Stylesheet und beginnt dann sofort mit der Anzeige des Inhaltes mit den verfügbaren eigenen Schriften. Die tatsächlich zu verwendenden Schriften, die als Webfont eingebunden sind, werden dann parallel dazu im Hintergrund geladen und der Inhalt mit der richtigen Schrift aktualisiert, sobald diese übertragen wurde. Das kann durchaus einige Sekunden dauern und auch mehrfach passieren (für jeden einzelnen Schriftschnitt), was mindestens ziemlich irritierend ist.

Die Lösung mit Data-URL

Als „Data-URL“ wird ein URL-Schema bezeichnet, mit dem man Binärdaten direkt in einer URL angeben kann, ohne auf eine externe Ressource verweisen zu müssen. Das Schema wurde bereits 1998 spezifiert und die Methode funktioniert mit allen gängigen Browsern. Siehe dazu die RFC 2397 und http://caniuse.com/#search=dataurl.

Für Binärdaten sieht es vereinfacht wie folgt aus:

data:<MIME-Type>;base64,<Daten kodiert als Base64>

Als Beispiel die Darstellung eines Bilds mit einer Data-URL (zur besseren Lesbarkeit stark gekürzt):

<img alt="Globus" src="data:image/png;base64,iVBORw0KGgo ... " />

Analog dazu kann man Data-URLs auch in Stylesheets verwenden (auch hier wieder entsprechend gekürzt):

.myclass {
  background-image: url(data:image/png;base64,iVBORw0KGgo ... );
}

Der große Vorteil ist, dass nun keine zusätzliche HTTP-Anfrage für das Laden des Bildes nötig ist, sondern die Daten bereits im HTML-Dokument oder dem Stylesheet enhalten sind. Für kleinere Grafiken, wie Symbole, die weniger als 1 KiB Daten umfassen, ist so eine Methode generell sinnvoll, da hier deutlich mehr Zeit für die HTTP-Anfrage benötigt wird, als für die eigentliche Datenübertragung.

URLs dürfen nicht beliebig lang werden. Bis zu 64 KiB sollten aber generell mit neueren Versionen von Firefox, Safari, Chrome, Internet Explorer oder Opera und den entsprechenden mobilen Varianten davon möglich sein.

Daher kann man die selbe Methode wie bei Bildern auch für Webfonts verwenden, wie hier am Beispiel der vorher erwähnten Schrift „Lato“, bei der jeder Schriftschnitt für sich auch als Base64 weniger als 64 KiB benötigt (zur besseren Lesbarkeit stark gekürzt).

Ein Hinweis zum Format: auch wenn nur WOFF (Web Open Font Format) angeboten wird, deckt dies die meisten aktuellen Browser ab, da selbst der Internet Explorer und Android-Browser oder iOS heutzutage WOFF unterstützen und nicht mehr EOT oder TTF benötigen.

@font-face {
    font-family: "Lato";
    src: url(data:font/woff;base64,d09GRgABAAAAALQ ... ) format("woff");
}

@font-face {
    font-family: "Lato"; 
    font-style: italic;
    src: url(data:font/woff;base64,d09GRgABAAAAALh ... ) format("woff");
}

@font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: bold; 
    src: url(data:font/woff;base64,d09GRgABAAAAALR ... ) format("woff");
}

@font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: bold;
    src: url(data:font/woff;base64,d09GRgABAAAAALm ... ) format("woff");
}

Das Stylesheet wird dadurch etwa 240 KiB größer, da die Schriften in Base64 kodiert etwa 30% mehr Platz benötigen. Allerdings kann dieser Platzbedarf durch die Verwendung von gzip-Komprimierung für die Übertragung der Daten stark verringert werden, so dass am Ende kaum mehr Daten übertragen werden müssen, als vorher mit Stylesheet und den vier separaten Webfonts.

Was in jedem Fall entfällt, sind die vier zusätzlichen Ladevorgänge. Selbst wenn man davon ausgeht, dass das Stylesheet aufgrund seiner Größe eine längere Ladezeit verursacht, ist der gesamte Ladevorgang dennoch schneller.

Vor dieser Maßnahme waren etwa 21 Zugriffe für das Laden der Startseite nötig und das Laden der Webfonts erfolgte mitunter erst 1 bis 1,5 Sekunden nach dem ersten Zugriff. Der gesamte Ladevorgang hat je nach Rahmenbedingungen etwa 2-3 Sekunden benötigt.

Nach der Änderung wie oben beschrieben, sind es nur noch 15 Zugriffe (einige Bilder habe ich bei der Gelegenheit ebenfalls als Data-URL eingebunden) und der gesamte Ladevorgang hat sich deutlich beschleunigt: Unter günstigen Umständen auch mit vorher geleertem Cache kaum mehr als eine Sekunde, im Schnitt aber dennoch spürbar schneller, besonders bei langsameren Verbindungen, wo jede zusätzliche Anfrage deutliche Verzögerungen verursacht.

Webfonts in Base64 umwandeln

Eine sehr einfache Variante zur Erzeugung der Base64-Daten ist http://dataurl.net/#dataurlmaker. Hier kann man die betreffende Datei per Drag&Drop in das Feld „Drag file here“ ziehen oder mit „Browse…“ auf der lokalen Festplatte auswählen und erhält umgehend die Base64-Variante davon in einem Textfeld, aus dem man sich den Inhalt in die Zwischenablage kopieren kann:

http://dataurl.net

Man sollte nur beachten, dass man die Angabe „application/octet-stream“ durch den Wert „font/woff“ ersetzt, bevor man die Daten in ein Stylesheet übernimmt. Auch die Länge der Data-URL sollte nicht über 65536 Bytes liegen (entsprechend 64 KiB).

Einschränkungen bei Data-URLs

Neben der schon erwähnten maximalen Länge für Data-URLs sollte noch ein weiterer Punkt beachtet werden. Die Überlegungen zur besseren Einbindung von Webfonts gehen davon aus, dass die Schriften (oder das im Beispiel gezeigten Bild) auch alle verwendet werden. Nur dann hat man auch einen Vorteil von dieser Methode.

Zur Erläuterung:

Wenn in Stylesheets sehr viele externe Ressourcen definiert sind, kann sich die generelle Umwandlung in Data-URLs auch negativ auswirken, weil die reine Datenübertragung des deutlich umfangreicheren Stylesheets länger dauert, als die einzelnen Anfragen, die vorher erfolgt sind. Browser fordern normalerweise nur die Elemente an, die sie aktuell auch benötigen. Werden nun in einem Stylesheet 50 Regeln mit Bildern definiert, von denen in einem Dokument nur vier verwendet werden, laden Browser auch nur diese vier Bilder und nicht alle 50. Je nach Datenmenge kann es daher sinnvoll sein, die Bilder weiterhin über externe URLs einzubinden.

Öffentlichen Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Wenn Du mich persönlich erreichen möchtest, siehe Impressum.