`font-display` für die Massen

Avatar of Jeremy Wagner
Jeremy Wagner am

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

Aktualisiert am 12. Januar 2017: Korrekte Support-Prüfungen sind jetzt Teil des Artikels. Informationen zum Wert block hinzugefügt. Kleinere Anpassungen und redaktionelle Änderungen. Viel Spaß!

Wenn Sie hier bei CSS-Tricks regelmäßig lesen, kennen Sie sich wahrscheinlich gut mit Webfonts aus. Vielleicht kennen Sie sogar ein paar nützliche Tricks, um die Ladeweise von Schriftarten zu steuern, aber haben Sie die CSS-Eigenschaft font-display verwendet?

Die CSS-Eigenschaft font-display ist in Chrome verfügbar und wird in Firefox und Safari eingeführt (aber Sie sollten die Browserunterstützung selbst überprüfen, da sich Dinge ständig ändern). Sie ist eine einfachere Methode, um das zu erreichen, wozu die Font Loading API sowie Drittanbieter-Skripte wie Bram Steins Font Face Observer in der Lage sind.

Wenn Ihnen all das neu ist, kein Problem. Sprechen wir zuerst ein wenig über das Standardverhalten beim Laden von Schriftarten in Browsern.

Schriftarten-Laden im Browser

Browser sind sorgfältig entwickelte Programme und leisten im Hintergrund vieles, was wir vielleicht nicht vermuten. Das Laden von Schriftarten ist da keine Ausnahme. Wenn ein Browser eine Schriftart von einem Webserver anfordert, werden alle Elemente, deren Stile diese Schriftart verwenden, verborgen, bis die Schriftart heruntergeladen wurde. Dies ist als "Flash of Invisible Text" oder FOIT bekannt.

Der FOIT-Effekt in Aktion

Dieses Verhalten dient dazu, uns davor zu "bewahren", dass Text zunächst in einer Systemschriftart gerendert wird, nur um dann zur benutzerdefinierten Typografie zu wechseln, sobald diese geladen ist. *Dieses* Verhalten ist als "Flash of Unstyled Text" oder FOUT bekannt.

FOIT mag besser klingen als FOUT, aber FOIT hat Auswirkungen auf Benutzer mit langsamen Verbindungen. Standardmäßig verstecken die meisten Browser Text bis zu 3 Sekunden, bevor sie Text in einer Fallback-Systemschriftart anzeigen, während sie auf das Laden einer Schriftart warten. Andere Browser wie Safari warten noch länger oder vielleicht unbegrenzt, was einige Benutzer mit unsichtbarem Text im Stich lässt, der möglicherweise nicht gerendert wird, wenn eine Schriftart-Anfrage ins Stocken gerät.

Wir können dieses Problem mit einer JavaScript-basierten Lösung lösen, um zu verfolgen, wann Schriftarten geladen werden. Wir stylen das Dokument so, dass es standardmäßig Systemschriften verwendet, und wenn wir feststellen, dass benutzerdefinierte Schriftarten geladen wurden, fügen wir dem Dokument eine CSS-Klasse hinzu, die dann die benutzerdefinierten Typografien auf das Dokument anwendet. Dieser Ansatz wurde bereits behandelt. Angenommen, Sie haben beispielsweise eine Seite, die Open Sans Regular für alle <p>-Elemente verwendet. Zunächst würden Sie CSS wie folgt verwenden:

p {
  font-family: "Helvetica", "Arial", sans-serif;
}

Während die Schriftart-Anfrage läuft, wird zunächst entweder Helvetica oder Arial (abhängig von den auf Ihrem System verfügbaren Schriftarten) angezeigt. Wenn wir per JavaScript verifiziert haben, dass Open Sans Regular geladen wurde, wenden wir die Klasse fonts-loaded auf das <html>-Element an, was Open Sans über diesen nächsten CSS-Teil auf <p>-Elemente anwendet:

.fonts-loaded p {
  font-family: "Open Sans Regular";
}

Diese Lösungen funktionieren, sind aber oft etwas unhandlich. Hier kommt die CSS-Eigenschaft font-display ins Spiel.

Sich mit font-display vertraut machen

font-display ist eine CSS-Eigenschaft, die ab Chrome 61, Chrome für Android, Opera und Safaris Technical Preview verfügbar ist. Unterstützung für diese Eigenschaft wird in Firefox 58 erwartet. Mit font-display können wir steuern, wie Schriftarten gerendert werden, ähnlich wie bei JavaScript-basierten Lösungen, nur jetzt durch eine praktische CSS-Einzeiler! font-display wird innerhalb von @font-face verwendet und akzeptiert die folgenden Werte:

  • auto: Der Standard. Es erfolgt das typische Browser-Verhalten beim Laden von Schriftarten. Dieses Verhalten kann FOIT sein oder FOIT mit einer relativ langen Unsichtbarkeitsperiode. Dies kann sich ändern, da Browseranbieter sich auf bessere Standardverhalten einigen.
  • swap: Fallback-Text wird sofort in der nächsten verfügbaren Systemschriftart im Schriftstapel gerendert, bis die benutzerdefinierte Schriftart geladen ist, in welchem Fall die neue Typografie swapped wird. Das ist es, was wir für Dinge wie den Haupttext wollen, wo Benutzer Inhalte sofort lesen können sollen.
  • block: Wie FOIT, aber die Unsichtbarkeitsperiode bleibt unbegrenzt bestehen. Verwenden Sie diesen Wert immer dann, wenn das Blockieren des Renderns von Text für eine potenziell unbegrenzte Zeitspanne vorzuziehen wäre. Es ist nicht sehr oft, dass block einem anderen Wert vorgezogen werden würde.
  • fallback: Ein Kompromiss zwischen block und swap. Es wird eine sehr kurze Zeitspanne (100 ms laut Google) geben, in der Text, der mit benutzerdefinierten Schriftarten gestylt ist, unsichtbar ist. Dann erscheint ungestylter Text, wenn die benutzerdefinierte Schriftart nicht vor Ablauf der kurzen Blockierungsperiode geladen wurde. Sobald die Schriftart geladen ist, wird der Text entsprechend gestylt. Dies ist großartig, wenn FOUT unerwünscht ist, aber Barrierefreiheit wichtiger ist.
  • optional: Funktioniert ähnlich wie fallback, da der betroffene Text zunächst für eine kurze Zeit unsichtbar ist und dann zu einem Fallback wechselt, wenn die Schriftart-Assets nicht vollständig geladen sind. Die Ähnlichkeiten enden dort jedoch. Die Einstellung optional gibt dem Browser die Freiheit zu entscheiden, ob eine Schriftart überhaupt verwendet werden soll, und dieses Verhalten hängt von der Verbindungsgeschwindigkeit des Benutzers ab. Bei langsamen Verbindungen sollten Sie damit rechnen, dass benutzerdefinierte Schriftarten möglicherweise gar nicht geladen werden, wenn diese Einstellung verwendet wird.

Nachdem wir nun die Werte kennen, die font-display akzeptiert, können wir sie auf eine @font-face-Regel anwenden. Hier ist ein Beispiel für die Verwendung des swap-Werts in einer @font-face für Open Sans Regular:

@font-face {
  font-family: "Open Sans Regular";
  font-weight: 400;
  font-style: normal;
  src: url("fonts/OpenSans-Regular-BasicLatin.woff2") format("woff2");
  font-display: swap;
}

Natürlich kürzen wir die @font-face in diesem Beispiel etwas ab, indem wir nur eine WOFF2-Datei verwenden, aber ich strebe Kürze an. In diesem Beispiel verwenden wir die Option swap für font-display, was ein Ladeverhalten ergibt, wie Sie es im folgenden Bild sehen:

Der Swap-Wert der `font-display`-Eigenschaft in Aktion.

Wenn wir das Laden von Schriftarten in JavaScript steuern, ist dies oft das gewünschte Verhalten. Wir möchten sicherstellen, dass der Text standardmäßig sichtbar ist und *dann* die benutzerdefinierte Typografie nach dem Herunterladen anwenden.

Aber was sind "Fallback-Texte"? Wenn Sie einen Wert für die font-family-Eigenschaft angeben, tun Sie dies mit einer durch Kommas getrennten Liste von Schriftartnamen. Dies wird als Schriftstapel bezeichnet. Der Fallback ist, welche Systemschriftart nach der primären (und vermutlich benutzerdefinierten) Typografie an der Reihe ist.

p {
  font-family: "Open Sans Regular", "Helvetica", "Arial", sans-serif;
}

In diesem Beispiel-Schriftstapel ist die benutzerdefinierte Schriftart Open Sans Regular. Die Systemschriften sind Helvetica und Arial. Wenn font-display: swap; verwendet wird, wird die erste Systemschriftart im Stapel angezeigt. Wenn die benutzerdefinierte Schriftart geladen wurde, wird sie aktiviert und ersetzt die zuvor angezeigte Systemschriftart. Die Verwendung der font-display-Werte fallback und optional stützt sich ebenfalls auf Systemschriften im Stapel, wenn dies erforderlich ist.

Meistens werden Sie swap verwenden.

Wenn Sie nicht wissen, welche Option Sie verwenden sollen, greifen Sie zu swap. Es ermöglicht Ihnen, benutzerdefinierte Schriftarten zu verwenden *und* Ihre Zugänglichkeit zu berücksichtigen. Wenn Sie Schriftarten haben, die "nett zu haben" sind, aber letztendlich verzichtbar wären, sollten Sie die Angabe von optional in Erwägung ziehen.

Was, wenn font-display nicht unterstützt wird?

Wie bei neueren Browserfunktionen ist die Unterstützung für font-display nicht allgegenwärtig. Daher haben Sie zwei Möglichkeiten in Bezug auf seine Verwendung:

  1. Sie können einfach font-display verwenden und das war's. Wenn andere Browser es nicht unterstützen, verhalten sie sich nach ihren Standardeinstellungen. Das ist nicht unbedingt schlecht, da es nichts kaputt macht, aber es ist möglicherweise nicht optimal für Sie.
  2. Sie können die Unterstützung für font-display erkennen und eine Alternative bereitstellen. Ziehen Sie dies in Betracht, wenn Zeit und Ressourcen es zulassen.

Wenn Sie sich für Option 2 entscheiden, müssen Sie die Unterstützung für font-display erkennen. Dies ist möglich, wie in diesem Fiddle gezeigt wird (entdeckt aus dieser Github-Diskussion).

try {
  var e = document.createElement("style");
  e.textContent = "@font-face { font-display: swap; }";
  document.documentElement.appendChild(e);
  var isFontDisplaySupported = e.sheet.cssRules[0].cssText.indexOf("font-display") != -1;
  e.remove();
} catch (e) {
  // Do something with an error if you want
}

Von hier aus können wir entscheiden, was basierend auf dem Wert der Variablen isFontDisplaySupported zu tun ist. Eine Möglichkeit, wie Sie diese Feature-Prüfung verwenden könnten, wäre, auf die Font Loading API zurückzugreifen, wenn font-display fehlt, wie folgt:

if (isFontDisplaySupported === false && "fonts" in document) {
  document.fonts.load("1em Open Sans Regular");
  document.fonts.ready.then(function(fontFaceSet) {
    document.documentElement.className += " fonts-loaded";
  });
}
else {
  // Maybe figure out your own strategy, but this might be sensible:
  document.documentElement.className += " fonts-loaded";
}

In diesem Beispiel behandelt die Font Loading API den Übergang, wenn isFontDisplaySupported false ist. Sobald die API weiß, dass eine Schriftart geladen wurde, können wir eine Klasse namens fonts-loaded auf das <html>-Tag anwenden. Mit dieser Klasse können wir dann CSS schreiben, das eine schrittweise Anwendung benutzerdefinierter Typografien ermöglicht:

p {
  font-family: "Helvetica", "Arial", sans-serif;
}

.fonts-loaded p {
  font-family: "Open Sans Regular";
}

Offensichtlich würden wir es vorziehen, einen CSS-Einzeiler wie font-display zu verwenden, um all diese Dinge für uns zu erledigen, aber zumindest haben wir die Möglichkeit, bei Bedarf auf eine andere Lösung zurückzugreifen. Mit der Zeit werden font-display (sowie die Font Loading API) möglicherweise in den meisten (wenn nicht allen) Browsern implementiert sein.

Was ist mit Drittanbieter-Schriftartenanbietern?

Wenn Sie Schriftarten über einen Drittanbieter-Service wie Google Fonts oder TypeKit einbetten, können Sie im Moment nicht viel tun. Drittanbieter-Dienste kontrollieren den Inhalt eines @font-face, das sie hosten. Erwägen Sie daher vielleicht, Ihre eigenen Schriftarten zu hosten (darüber spreche ich in diesem Artikel).

Im Laufe der Zeit werden Anbieter font-display möglicherweise zu einer konfigurierbaren Option machen, wenn Sie einen Embed-Code von ihrem Dienst abrufen. font-display wird aktiv diskutiert für eine mögliche Implementierung in Google Fonts, aber gehen Sie nicht davon aus, dass jeder Drittanbieter-Dienst es unbedingt implementieren wird.

Update: Google Fonts verwendet jetzt standardmäßig swap. Hurra!

In jedem Fall ist font-display eine willkommene Ergänzung zur Landschaft der Webtypografie. Es vereinfacht erheblich, was ansonsten eine unhandliche Aufgabe in JavaScript ist. Probieren Sie font-display selbst aus und sehen Sie, was es für Sie und Ihre Benutzer tun kann!


Cover of Web Performance in Action

Jeremy Wagner ist der Autor von Web Performance in Action von Manning Publications. Verwenden Sie den Gutscheincode sswagner, um 42% zu sparen!

Schauen Sie ihn sich auf Twitter an: @malchata