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.

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 Typografieswapped 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, dassblockeinem anderen Wert vorgezogen werden würde.fallback: Ein Kompromiss zwischenblockundswap. 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 wiefallback, 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 Einstellungoptionalgibt 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:

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:
- Sie können einfach
font-displayverwenden 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. - Sie können die Unterstützung für
font-displayerkennen 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!
Würde das Hinzufügen der JS-Bedingung zum Testen, ob dies unterstützt wird, den Vorteil der Verwendung davon aufheben?
Ich bin mir nicht ganz sicher, was Sie meinen – Meinen Sie angesichts der Tatsache, dass mein im Artikel geschriebener Feature-Detection-Code nicht zu 100% zuverlässig war? Dann ja, in einigen Situationen mag es das. Wenn die Unterstützung des Features jedoch richtig und zuverlässig erkannt wird, dann würde jeder JavaScript-Fallback-Code nur in dem Fall ausgeführt, dass
font-displaynicht verfügbar ist.Sie können Feature Queries dafür verwenden https://hacks.mozilla.org/2016/08/using-feature-queries-in-css/
Ich habe es versucht, aber ohne Erfolg: https://css-tricks.de/font-display-masses/#comment-1603606
Könnten Sie @supports für die Feature-Erkennung anstelle von JS verwenden? (und Fallback für alle anderen)?
Ja! Das könnten Sie durchaus. Mein einziges Zögern bei dieser Methode ist, dass Feature-Queries und die @supports JS-API nicht universell, äh, unterstützt werden. In diesem Fall würde ich eine einzelne, breiter unterstützte Methode bevorzugen, die die Unterstützung für
font-display(oder jede Funktion, wirklich) ermittelt.Gibt es Browser, die font-display, aber nicht @supports unterstützen?
Guter Punkt, tatsächlich. Obwohl ich bei der Überprüfung in Chrome Canary mit diesem Code in JavaScript...
…ist es mir weniger klar, ob supports wie beabsichtigt funktioniert. Ich erhalte dasselbe Ergebnis, wenn ich die Unterstützung für
unicode-rangemitCSS.supportsprüfe.Daher bin ich mir nicht sofort sicher, wie man mit
CSS.supportsnach@font-face-spezifischen Regeln suchen würde. Ich bin relativ neu in der Verwendung der Supports-API. Die Verwendung der Feature-Query-Syntax liefert ähnliche Ergebnisse:Wenn jemand Ideen hat, würde ich mich freuen, davon zu hören, denn das wäre eine viel einfachere Methode, um jede CSS-Funktionsunterstützung zu prüfen, geschweige denn
font-display.Es sei denn, ich verpasse etwas (was ich wahrscheinlich tue), es wird in Canary nicht unterstützt (es gibt keine Syntaxhervorhebung für font-display, wenn die CSS-Datei im Quellcode bearbeitet wird) und ich konnte keine Referenz dazu in den Flags finden? Dasselbe gilt für Opera. Obwohl vorgeschlagen wird, dass beides funktionieren sollte? https://developers.google.com/web/updates/2016/02/font-display?hl=en
Beim Versuch, mit @supports (css) oder CSS.supports (js) zu testen, komme ich nicht weiter als Sie, wobei alle 3 Browser false melden. Sehr verwirrend.
Brendan
Hallo zusammen,
Es kann nicht mit CSS-Supports funktionieren.
Ich habe hier einen Bug-Report erstellt und er stellte sich als ungültig heraus, wie Chromium-Entwickler hier erklären:
https://bugs.chromium.org/p/chromium/issues/detail?id=600137
"Dies funktioniert tatsächlich wie beabsichtigt. font-display ist ein Deskriptor, kein Property, und CSS.supports ist nur für Properties (es gibt sowohl einen font-family Deskriptor als auch eine font-family Property, daher funktioniert es in CSS.supports)."
Ich nehme an, das ergibt Sinn, interessant.
Hallo Jeremy,
Diese Feature-Erkennung für font-display funktioniert möglicherweise nicht. Sie funktioniert in Chrome (wenn aktiviert), sollte aber nicht.
Sie funktioniert nicht in Firefox (wenn aktiviert), wie sie sollte.
Heute hat mir ein Mozilla/Firefox-Entwickler gesagt, dass dies der Weg zur Feature-Erkennung ist:
https://jsfiddle.net/p7g8y7du/
Der Hintergrund ist hier:
https://bugzilla.mozilla.org/show_bug.cgi?id=1296373
Danke dafür! Meine Technik zur Feature-Erkennung ist anscheinend nicht kugelsicher. :)
Chris hat den Artikel aktualisiert, um auf eine Github-Diskussion zu verweisen, in der Sie dies erwähnt haben. Ich habe nicht die Möglichkeit, den Artikel zu aktualisieren, daher liegt es an Chris' Ermessen, ob er mich bittet, den Code im Artikel zu aktualisieren (was ich tun würde, wenn er es so verlangte).
Nochmals vielen Dank!
Ich würde FOIT gegenüber FOCF bevorzugen – Flackern von Schriftarten IMO ist es störender, wenn Text die Schriftart wechselt, als wenn Text von unsichtbar zu sichtbar wird.
Tatsächlich haben wir vor ein paar Jahren hart daran gearbeitet, einen Weg um FOUT (Flash of Unstyled Text) zu finden, was genau die Situation war, die der
swap-Wert hier geschaffen hat. Ich schätze, alles Alte ist wirklich wieder neu.Ja, natürlich, wenn Sie eine schnelle Verbindung haben. Aber wenn nicht, ist es besser, ungestylten Text für ein paar Sekunden (oder mehr) zu sehen, als gar nichts zu sehen. Mit FOUT ist der Übergang "hässlicher", aber die Website ist früher nutzbar.
Danke für den Artikel, ich war mir dieser Möglichkeit nicht bewusst und wollte schon lange etwas Ähnliches, um transparenten Text zu vermeiden.
Zum Problem mit externen Anbietern: Vielleicht ist die wahre Antwort – sie nicht zu verwenden? Ich ziehe es immer vor, die Schriftarten und das CSS lokal zu kopieren und jede Anfrage an einen externen Anbieter wie Google Fonts zu vermeiden, sodass ein Teil des Codes nicht von einer externen Website abhängig ist, die ihn ohne Kontrolle ändern kann.
Ich kann definitiv verstehen, warum manche externe Anbieter meiden wollen, aber diese Anbieter haben tief in die Taschen greifen müssen, um Ressourcen weltweit für eine schnellere Bereitstellung bereitzustellen. Ich denke, jeder seriöse Drittanbieter-Anbieter wird dies irgendwann konfigurierbar machen.
Nichtsdestotrotz könnten Sie immer tun, was Sie bereits tun, aber einen CDN-Dienst wie Cloudflare vor Ihre Website schalten, was einen ähnlichen Effekt erzielen würde. Hm. Vielleicht sollte ich das für meine eigene Website tun...
Danke fürs Lesen!
Wie sind wir von "OMG, FOUT = schlecht!" dazu gekommen, dass es der gewünschte Effekt ist?
Barrierefreiheit. Wenn Browser das Rendern von Text für eine inakzeptabel lange Zeit blockieren, ist die Möglichkeit von permanent unsichtbarem Text für manche ein inakzeptables Ergebnis.
Fair genug, es ist nur lustig, das Hin und Her, obwohl, sicher.
Wie jemand in einem anderen Kommentar sagte, alles Alte ist wieder neu, aber dieses Mal aus gutem Grund. :) Danke fürs Lesen, Mann.
Hallo Jeremy,
Danke für das Teilen dieses Artikels, ich hoffe, die Browser werden bald eine Unterstützung dafür anbieten!
Warum fällt der Browser nicht auf den nächsten Eintrag in der
font-family-Liste zurück? Es scheint der offensichtlichste Weg zu sein, das Problem zu bewältigen.Beispiel
Ich setze
font-family: "Asap", Arial;Ich lade die Seite, die Webfont wird noch geladen, also ist
Asapimmer noch nicht verfügbar, der Browser sollte zu Arial zurückfallen und sobald die Webfont geladen ist (verfügbar), sollte sie wechseln.Ist das nicht sinnvoll?
Ich frage mich, warum Sie nicht die classlist API verwenden, um CSS-Klassen zu verwalten? Sie verketten Strings ...
Wenn alles, was ich tue, darin besteht, eine Klasse zum HTML-Element hinzuzufügen, kann ich die breiteste Abdeckung erzielen, indem ich einfach die
fonts-loaded-Klasse verkette (classListhat eine Unterstützung von etwa 90 % in Browsern weltweit). Wenn ich Dinge wie das Umschalten/Entfernen benötige, verwende ich in diesem FallclassList. Ich gebe zu, es ist eine etwas pedantische Art, es zu tun.Was ist mit 3rd Bash Font Companies?
Wenn Sie Schriftarten einbetten, die mit einem Drittanbieter-Dienst wie Google Fonts oder TypeKit zusammenarbeiten, gibt es nicht viel, was Sie tun können. Der Schriftarten-Display muss innerhalb einer @font-face-Deklaration verwendet werden. Da Sie die CSS nicht kontrollieren, die der Schriftarten-Dienstleister bereitstellt, können Sie die Existenz des Schriftarten-Display in diesem Fall nicht kontrollieren, geschweige denn den Wert, der ihm übergeben wird. http://www.iadmission.org/
Also hat noch niemand eine Lösung gefunden, die sowohl FOIT als auch FOUT beheben kann?