Vor einigen Jahren bestand die Gemeinschaft darin, dass beim Laden einer Website alle Schriftarten ausgeblendet werden sollten, bis die richtigen Ressourcen heruntergeladen wurden. Viele Designer und Entwickler argumentierten, dass die Standardmethode zum Laden von Schriftarten, die "Flash of Unstyled Text" oder FOUT genannt wird, für Benutzer ärgerlich sei. Dies ist, wenn die Fallback-Webschriftart, sagen wir Georgia, zuerst auf dem Bildschirm angezeigt und dann durch eine benutzerdefinierte Schriftart ersetzt wird, wenn sie geladen wurde. Sie argumentierten, dass dies zu einem kohärenteren Browsererlebnis führen würde, wenn Benutzer einfach auf alles warten würden, bis es heruntergeladen ist, anstatt diesen Wechsel von einer Schriftart zu einer anderen zu erleben.
Aber heute ist das nicht mehr der Fall.
Tatsächlich wird diese Praxis, einen Browser zu erlauben, den gesamten Text auszublenden, der mit einer benutzerdefinierten Schriftart gestylt werden soll, jetzt als 'Flash of Invisible Text' oder FOIT bezeichnet und oft als die schlechteste aller möglichen Optionen angesehen. Scott Jehl argumentiert, dass dies sowohl für die Leistung als auch für die Benutzerfreundlichkeit eine ziemlich schlechte Idee ist.
Die FOIT ist am problematischsten in Browsern wie iOS Safari, der Text bis zu 30 Sekunden lang ausblendet, bevor er aufgibt und ihn mit einer Standard-Schriftart rendert, aber sie kann auch in Browsern mit kürzeren Ausblendzeiten wie Chrome, Firefox und Opera beobachtet werden.
Ebenso heißt es auf der Typekit-Hilfeseite zu diesem Thema: "Der FOUT-Ansatz macht Seiten sofort nutzbarer, insbesondere bei langsamen Netzwerkverbindungen." Als Designer und Entwickler müssen wir uns also zwischen FOUT oder FOIT entscheiden.
Flash of Invisible Text
- Schriftart beginnt mit dem Download
- Text ist unsichtbar, während die Web-Schriftart angefordert wird
- Die Zeit vergeht sehr langsam
- Web-Schriftart wird geladen
- Text mit der Web-Schriftart wird angezeigt
Flash of Unstyled Text
- Schriftart beginnt mit dem Download
- Sofort Text mit
font-familyFallback anzeigen - Web-Schriftart wird geladen
- Text mit Fallback-Schriftart wird durch die Web-Schriftart ersetzt
Der Unterschied zwischen diesen beiden Ansätzen ist oft verblüffend. Scott erwähnt, dass der FOIT-Ansatz dazu führte, dass der Text auf der Filament Group-Website bei einer 3G-Verbindung nach 2,7 Sekunden sichtbar war, während der FOUT-Ansatz den Text nach 0,6 Sekunden sichtbar machte. Wenn wir möchten, dass unsere Benutzeroberflächen so schnell wie möglich wirken, dann müssen wir die FOUT-Methode verwenden; Benutzererfahrung und Netzwerkleistung sind definitiv die Hauptpriorität bei dieser Technik.
Probleme mit dem FOUT-Ansatz
Dieser Ansatz hat sicherlich mehrere Nachteile. Zum Beispiel kann es beim Wechsel zwischen Fallback- und schicker Schriftart zu einer Menge Ruckeln und Wackeln kommen, da die Schriftstärke und die x-Höhe unterschiedlich sind. Folglich möchte ein Unternehmen aus Branding-Gründen möglicherweise nur in einer bestimmten Schriftart kommunizieren, aber mit dieser FOUT-Technik ist das offensichtlich unmöglich.
Manchmal können diese Nachteile gemildert werden. Sehen Sie sich zum Beispiel die Website von Bram Stein an, auf der der leichte Flash von unformatiertem Text augenblicklich ist und das Format der Seite vor und nach Abschluss des Ladens fast unverändert bleibt. Wenn wir außerdem eine Anzeigeschriftart verwenden möchten, für die wir keine geeignete Fallback-Schriftart finden können, dann können wir stattdessen vielleicht SVG zur Anzeige dieses Textes verwenden.
Durchgehen der FOUT-Technik
Ich habe in letzter Zeit mit dem Web Font Loader experimentiert, der Entwicklern etwas mehr Kontrolle darüber gibt, wie Schriftarten während des FOUT behandelt werden. Zuerst müssen wir den Web Font Loader-Code in unser Markup einbetten.
(function(d) {
var wf = d.createElement('script'), s = d.scripts[0];
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js';
s.parentNode.insertBefore(wf, s);
})(document);
Dies lädt das Skript asynchron auf die Seite, sodass Sie es kurz vor dem Ende des body oder im head hinzufügen können und die restlichen Ressourcen nicht blockiert werden. Diese Technik ist nützlich für die IE9-Unterstützung, aber wenn das für unser Projekt nicht wichtig ist, können wir stattdessen diese Methode verwenden.
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js" async></script>
Sobald wir das Skript haben, können wir unsere Schriftarten hinzufügen. In diesem Nebenprojekt habe ich mit Schriftarten experimentiert, die mit @font-face von der Typonine Foundry bereitgestellt werden, die wir als link im head unseres Markups hinzufügen.
<link rel="preconnect" href="https://fonts.typonine.com/" crossorigin>
preconnect ist hier nützlich, da es automatisch den Netzwerkhändedruck für uns durchführt; bevor wir die Schriftarten aus unserem Skript anfordern, haben wir bereits alle Informationen, die der Browser benötigt, um diese Assets abzurufen, was diesen Vorgang nur ein wenig schneller macht. (Danke an Ilya Grigorik für den Vorschlag, auch das crossorigin-Attribut hier zu verwenden.)
Nun können wir mit dem WebFontConfig-Objekt überprüfen, ob diese Schriftarten auf unserer Seite geladen wurden.
WebFontConfig = {
custom: {
families: [
'Nocturno Display Medium 3',
'Nocturno Book 2',
'Nocturno Regular Italic 24',
'Nocturno Regular 26',
'Nocturno Regular 25'
],
urls: [
'https://fonts.typonine.com/WF-000000-001254.css',
'https://fonts.typonine.com/WF-000000-001255.css'
]
},
timeout: 2000
};
Das custom-Objekt teilt dem Web Font Loader mit, dass wir Schriftarten aus einem externen Stylesheet laden möchten, aber mit diesem Loader können wir bei Bedarf auch Schriftarten von Typekit, Google, Fontdeck oder Fonts.com verwenden. Mit dem families-Array identifizieren wir alle Font-Family-Namen, die wir sonst direkt im CSS verwenden würden.
Sie werden feststellen, dass ich ein timeout von 2 Sekunden eingestellt habe. Das ist eine völlig subjektive Angabe, aber ich denke, das ist reichlich Zeit, um eine Netzwerkanfrage zu stellen – länger als das ist der Benutzer wahrscheinlich mit einer schlechten Verbindung unterwegs und will sowieso nur den Inhalt.
Sobald der Loader mit dem Laden dieser Schriftarten fertig ist, fügt er diese Klassen zum html-Element hinzu.
<html class="wf-nocturnoregularitalic24-n4-active wf-nocturnoregular26-n4-active wf-nocturnoregular25-n4-active wf-nocturnodisplaymedium3-n4-active wf-nocturnobook2-n4-active wf-active">
<!-- markup for the website goes here -->
</html>
Diese Klassen sind die Haken, die wir brauchen, um die Seite je nach Ladezustand der Schriftarten zu stylen. Es gibt jedoch weitere Klassen, die hinzugefügt werden können, um uns zu helfen.
loading: Ausgelöst, wenn alle Schriftarten angefordert wurden.active: Ausgelöst, wenn die Schriftarten gerendert wurden.inactive: Ausgelöst, wenn der Browser keine verknüpften Schriftarten unterstützt oder wenn keine der Schriftarten geladen werden konnte.fontloading: Wird einmal für jede geladene Schriftart ausgelöst.fontactive: Wird einmal für jede gerenderte Schriftart ausgelöst.fontinactive: Wird ausgelöst, wenn die Schriftart nicht geladen werden kann.
In unserem Stylesheet können wir nun die richtige Familie mit der Klasse .wf-active festlegen.
$fallback: Georgia, serif;
h1, .h1 {
font-family: $fallback;
.wf-active & {
font-family: "Nocturno Display Medium 3";
}
}
So sehen unsere Benutzer sofort die Schriftarten, die in der $fallback-Variable enthalten sind, aber sobald unsere .wf-active-Klasse vom Web Font Loader hinzugefügt wurde, werden diese Schriftarten gegen die schicke Web-Schriftart ausgetauscht. Wir verfolgen nun einen progressiven Erweiterungsansatz für das Laden von Schriftarten.
Vermeidung von Ruckeln
Ein Problem, das ich bemerkte, war, dass nach dem Laden dieser Schriftarten die Anzahl der Wörter, die auf eine Zeile passten, sich änderte und bestimmte Elemente aufgrund dieser neuen Ergänzungen auf der Seite zu breit oder zu klein wurden.
Um dies zu beheben, können wir immer eine andere Kombination aus font-size und line-height einstellen, um dies zu einer reibungsloseren Erfahrung zu machen.
h1, .h1 {
font-size: 30px;
line-height: 35px;
font-family: Georgia, serif;
.wf-active & {
font-size: 26px;
line-height: 30px;
font-family: "Nocturno Display Medium 3";
}
}
Minimierung des Flash of Unstyled Text
Nach dem ersten Seitenaufruf empfiehlt The Filament Group, einen Cookie zu setzen, damit wir nicht jedes Mal diesen Flash of Unstyled Text haben, während die Klasse .wf-active auf das Markup angewendet wird. Aber in meinem Experiment habe ich einfach nur statisches Markup verwendet, sodass die Cookie-Option nicht wirklich verfügbar war. Stattdessen habe ich eines der vielen Ereignisse im Web Font Loader verwendet, um sessionStorage zu aktualisieren, wie hier:
WebFontConfig = {
// other options and settings
active: function() {
sessionStorage.fonts = true;
}
}
Vergessen Sie nicht, die vollständige Liste der verfügbaren Ereignisse zu überprüfen. Aber mit diesem speziellen Ereignis können wir sofort im head des Dokuments überprüfen, ob dieser Schlüssel in sessionStorage vorhanden ist, und wenn ja, können wir dann so schnell wie möglich den Klassennamen zum html-Element hinzufügen.
<head>
<script>
(function() {
if (sessionStorage.fonts) {
console.log("Fonts installed.");
document.documentElement.classList.add('wf-active');
} else {
console.log("No fonts installed.");
}
})();
</script>
</head>
Dies blockiert nicht vollständig den Flash of Unstyled Text, der wahrscheinlich sowieso ein Problem sein wird, aber es ist sicherlich eine Verbesserung gegenüber FOIT.
Das Laden von Schriftarten ist entscheidend für gute Typografie
Nachdem ich mit dieser Technik herumgespielt hatte, stellte ich fest, dass die Erfahrung meine Ansicht über gute Typografie im Web komplett veränderte.
Aber wenn Sie Ideen haben, wie die oben gezeigte Methode verbessert werden kann, lassen Sie es uns bitte in den Kommentaren wissen.
Die Eigenschaft
font-size-adjustkann bei FOUT und Reflow helfen. Sie funktioniert derzeit nur in Firefox, aber Chrome arbeitet aktiv daran, da Text-Reflow auf Mobilgeräten teuer ist.Ich mochte es nicht, als Browser anfingen, FOIT zu implementieren, daher bin ich froh, dass dies wieder auf der Tagesordnung steht. Ich dachte immer, es sei eine Eitelkeitslösung, die nicht von der Benutzerfreundlichkeit getragen wurde. Hoffentlich werden die Browser anfangen, das eigentliche Problem zu lösen (den Platz verlieren wegen Reflow ist Mist) und die ästhetisch ansprechende, aber schlechte Erfahrung des Verbergens von Text, bis die Schriftart geladen ist, aufgeben.
Da ich in Australien lebe, wo langsame Internetverbindungen üblich sind (für mich ADSL-Geschwindigkeiten und unwahrscheinlich, dass sich das bald ändert), ist das Problem ziemlich offensichtlich, und wenn ich auf Websites stoße, die FOUT anstelle von FOIT verwenden, finde ich es eine bessere Erfahrung, weil ich lieber den Inhalt lesen möchte, anstatt zu warten. Es ist nicht so, dass Systemschriftarten von Natur aus hässlich sind, sie sind nur für die meisten Websites nicht "markenkonform".
FOIT wäre in Ordnung, wenn es wirklich ein Blitz wäre, aber öfter als nicht ist es für mich eher eine lange Pause als ein schneller Blitz.
Wenn ich das richtig verstehe, lädt dieser Ansatz die Webfonts dynamisch über die Bibliothek. Wäre es nicht schneller, die Schriftarten über die Stylesheet-Datei selbst zu laden (
@font-face) und dann Tools wie FontFaceObserver zu verwenden, um zu "erkennen", wann sie bereit sind, um diewf-active-Klasse hinzuzufügen?Ich bin mir nicht sicher, wie die Leistungsunterschiede zwischen FontFace Observer und dieser Technik wären, aber ich würde gerne mehr darüber lesen!
Ja, Filament Group hat es empfohlen. Es wird verwendet, um die FOIT zu reduzieren, die Browser erzeugen, wenn sie denken, dass sie die Schriftart bereit haben.
Hallo – interessanter Artikel! Gibt es eine Demo irgendwo? Danke :)
Toller Artikel Robin!
Eine Sache hat mich aber verwirrt. Nicht, dass es viel ausmacht, aber warum war die Cookie-Option bei rein statischem Inhalt für Sie nicht verfügbar? Wenn Sie Zugriff auf sessionStorage haben, was würde Sie davon abhalten, Cookies in einer JS-Umgebung zu verwenden?
Danke! Ich habe ein bisschen recherchiert und viele Leute auf StackOverflow empfohlen, bei serverseitig verwendeten Daten bei Cookies zu bleiben, während
localStorageodersessionStoragefür clientseitige Daten verwendet werden sollten. Es gibt aber kein Problem, dies stattdessen mit Cookies zu tun, zumindest soweit ich weiß.Danke für die Klarstellung. Ich habe den Artikel so gelesen, als hätten Sie auf eine technische Einschränkung gestoßen, anstatt einfach einer Konvention zu folgen.
Tolle Beschreibung! In Ihrem preconnect-Beispiel gibt es einen kleinen Fehler: Sie benötigen ein zusätzliches "crossorigin"-Attribut [1] am Element, um die "richtige Art" (eine ohne weitere Anfragen mit Anmeldeinformationen) von Socket zum Abrufen von Schriftarten zu öffnen. Es ist verwirrend, ich weiß...
[1] http://w3c.github.io/resource-hints/#preconnect
Danke, Ilya! Ich habe den Beitrag mit Ihrem Vorschlag aktualisiert.
Ich mag Ihren
sessionStorage-Ansatz viel mehr als den Cookie-Ansatz von Filament Group. Aber ich bin immer noch frustriert, dass Webfonts sooo schwierig sein müssen.Ich hoffe, dass System-Schriftarten weiter an Popularität gewinnen. Der moderne Roboto-, Segoe UI-, San Francisco-Stack ist in vielen Szenarien eigentlich ganz gut.
Neugierig... würden Sie das tun, wenn Sie eine selbst gehostete Web-Schriftart hätten? Wir müssen für ein Projekt 2 Schriftgesichter verwenden, die zusammen 400 KB ergeben (wir konnten sie nicht davon abbringen).
Hallo. Ein paar Fragen.
Was ist, wenn ich mehrere Schriftarten mit demselben Familiennamen, aber mit unterschiedlichen Gewichten und Stilen habe? Ich habe MY_FONT mit Gewicht 400, 500 und 700 + 400 und 500 kursiv. Können Sie das richtig zum Laufen bringen?
Und was ist, wenn der Benutzer kein JS aktiviert hat? Oh ja, vielleicht die @font-face-Schriftart auf .no-js auslösen.
Ich habe alle meine Schriftarten lokal und verwende nicht/kann nicht die URL zum Herunterladen der Schriftarten verwenden.
Wäre es möglich, eine Web-Schriftart in eine andere zu verwandeln, um einen Flash zu vermeiden? Wie Fade Out -> Fade In? Nur eine Idee...