Zach Leatherman hat eine umfassende Liste von Strategien zum Laden von Schriftarten zusammengestellt, die im Bereich der Webentwicklung weit verbreitet ist. Ich habe mir diese Liste schon einmal angesehen, war aber so eingeschüchtert (und verwirrt), dass ich beschloss, *gar nichts* zu tun. Ich weiß nicht, wie ich am besten mit dem Laden von Schriftarten beginnen soll, und ich möchte mich beim Durchgehen dieser Liste nicht dumm fühlen.
Heute habe ich mir Zeit genommen, um mich hinzusetzen und es herauszufinden. In diesem Artikel möchte ich mit Ihnen die besten Ladestrategien teilen und erklären, wie Sie alle davon umsetzen können.
Die besten Strategien
Zach empfiehlt in seinem Artikel zwei Strategien
- FOUT with Class – Bester Ansatz für die meisten Situationen. (Dies funktioniert, egal ob wir ein Font-Hosting-Unternehmen nutzen oder unsere eigenen Schriftarten hosten.)
- Critical FOFT – Performantester Ansatz. (Dies funktioniert nur, wenn wir unsere eigenen Schriftarten hosten.)
Bevor wir uns diesen beiden Strategien widmen, müssen wir die Akronyme klären, damit Sie verstehen, was Zach meint.
FOIT, FOUT, FOFT
Die Akronyme lauten wie folgt:
- FOIT steht für flash of invisible text (Aufblitzen unsichtbaren Texts). Wenn Web-Schriftarten geladen werden, blenden wir den Text aus, sodass Benutzer nichts sehen. Wir zeigen den Text erst an, wenn die Web-Schriftarten geladen sind.
- FOUT steht für flash of unstyled text (Aufblitzen ungestylten Texts). Wenn Web-Schriftarten geladen werden, zeigen wir Benutzern eine Systemschriftart an. Wenn die Web-Schriftart geladen ist, ändern wir den Text zurück zur gewünschten Web-Schriftart.
- FOFT steht für flash of faux text (Aufblitzen von Fälschungstext). Dieses ist kompliziert und bedarf weiterer Erklärung. Wir werden es im Detail besprechen, wenn wir zum FOFT-Abschnitt kommen.
Selbst gehostete Schriftarten vs. Cloud-gehostete Schriftarten
Es gibt zwei Hauptmethoden, Schriftarten zu hosten:
- Verwenden Sie einen Cloud-Anbieter.
- Hosten Sie die Schriftarten selbst.
Wie wir Schriftarten laden, hängt stark davon ab, welche Option Sie wählen.
Schriftarten mit Cloud-gehosteten Schriftarten laden
Es ist oft einfacher, Cloud-gehostete Schriftarten zu verwenden. Der Anbieter gibt uns einen Link zum Laden der Schriftarten. Wir können diesen Link einfach in unser HTML einfügen und erhalten unsere Web-Schriftart. Hier ist ein Beispiel, bei dem wir Web-Schriftarten von Adobe Fonts laden (früher bekannt als Typekit).
<link rel="stylesheet" href="https://use.typekit.net/your-kit-id.css">
Leider ist dies nicht der beste Ansatz. Der href blockiert den Browser. Wenn das Laden der Web-Schriftart hängen bleibt, können die Benutzer während des Wartens nichts tun.
Typekit stellte früher JavaScript zur Verfügung, das eine Schriftart asynchron lädt. Es ist schade, dass sie diese JavaScript-Version nicht mehr anbieten. (Der Code funktioniert zwar immer noch, aber ich habe keine Ahnung, wann oder ob er aufhören wird zu funktionieren.)
Das Laden von Schriftarten von Google Fonts ist *etwas* besser, da es font-display: swap bereitstellt. Hier ist ein Beispiel, bei dem wir Lato von Google Fonts laden. (Der Parameter display=swap löst font-display: swap aus.)
<link
href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
/>
Schriftarten mit selbst gehosteten Schriftarten laden
Sie können Ihre Schriftarten nur selbst hosten, wenn Sie die Lizenz dazu haben. Da Schriftarten teuer sein können, entscheiden sich die meisten Leute stattdessen für einen Cloud-Anbieter.
Es gibt jedoch eine günstige Möglichkeit, an Schriftarten zu gelangen. Design Cuts veranstaltet gelegentlich Font-Angebote, bei denen Sie extrem hochwertige Schriftarten für nur 29 $ pro Bundle erhalten können. Jedes Bundle kann bis zu 12 Schriftarten enthalten. Ich habe Klassiker wie Claredon, DIN, Futura und eine ganze Reihe von Schriftarten bekommen, mit denen ich durch das Beobachten ihrer Newsletter für diese Angebote spielen kann.
Wenn wir Schriftarten selbst hosten wollen, müssen wir zwei weitere Konzepte verstehen: @font-face und font-display: swap.
@font-face
@font-face ermöglicht es uns, Schriftarten in CSS zu deklarieren. Wenn wir Schriftarten selbst hosten wollen, müssen wir @font-face verwenden, um Ihre Schriftarten zu deklarieren.
In dieser Deklaration können wir vier Dinge angeben:
font-family: Dies teilt CSS (und JavaScript) den Namen unserer Schriftart mit.src: Pfad zur Schriftart, damit diese geladen werden kannfont-weight: Die Schriftstärke. Standardwert ist 400, wenn weggelassen.font-style: Ob die Schriftart kursiv dargestellt werden soll. Standardwert ist normal, wenn weggelassen.
Für src müssen wir mehrere Schriftformate angeben. Für ein praktisches Maß an Browserunterstützung können wir woff2 und woff verwenden.
Hier ist ein Beispiel, bei dem wir Lato über @font-face laden.
@font-face {
font-family: Lato;
src: url('path-to-lato.woff2') format('woff2'),
url('path-to-lato.woff') format('woff');
}
@font-face {
font-family: Lato;
src: url('path-to-lato-bold.woff2') format('woff2'),
url('path-to-lato-bold.woff') format('woff');
font-weight: 700;
}
@font-face {
font-family: Lato;
src: url('path-to-lato-italic.woff2') format('woff2'),
url('path-to-lato-italic.woff') format('woff');
font-style: italic;
}
@font-face {
font-family: Lato;
src: url('path-to-lato-bold-italic.woff2') format('woff2'),
url('path-to-lato-bold-italic.woff') format('woff');
font-weight: 700;
font-style: italic;
}
Wenn Sie keine woff2- oder woff-Dateien haben, können Sie Ihre Schriftdateien (entweder OpenType oder TrueType) in einen Font-Face-Generator hochladen, um diese zu erhalten.
Als Nächstes deklarieren wir die Web-Schriftart in einer font-family-Eigenschaft.
html {
font-family: Lato, sans-serif;
}
Wenn Browser ein Element mit der Web-Schriftart parsen, lösen sie einen Download der Web-Schriftart aus.
font-display: swap
font-display akzeptiert einen von vier möglichen Werten: auto, swap, fallback und optional. swap weist Browser an, den Fallback-Text anzuzeigen, bevor die Web-Schriftarten geladen sind. Mit anderen Worten: swap löst für selbst gehostete Schriftarten FOUT aus. Erfahren Sie mehr über andere Werte aus dem CSS-Tricks-Almanach.
Die Browserunterstützung für font-display: swap ist heutzutage ziemlich gut, sodass wir es in unseren Projekten verwenden können.
Diese Daten zur Browserunterstützung stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 60 | 58 | Nein | 79 | 11.1 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 11.3-11.4 |
FOUT vs. FOUT mit Klasse
FOUT steht für flash of unstyled text (Aufblitzen ungestylten Texts). Sie wollen immer FOUT statt FOIT (flash of invisible text), weil es für Benutzer besser ist, Wörter in Systemschriftarten zu lesen, als Wörter in unsichtbarer Tinte. Wir haben bereits erwähnt, dass font-display: swap Ihnen die Möglichkeit gibt, FOUT nativ zu nutzen.
FOUT with Class erzielt die gleichen Ergebnisse – FOUT –, verwendet aber JavaScript, um die Schriftarten zu laden. Die Mechanik ist wie folgt:
- Erstens: Systemschriftarten laden.
- Zweitens: Web-Schriftarten über JavaScript laden.
- Drittens: Wenn die Web-Schriftarten geladen sind, fügen Sie dem
<html>-Tag eine Klasse hinzu. - Viertens: Ersetzen Sie die Systemschriftart durch die geladene Web-Schriftart.
Zach empfiehlt das Laden von Schriftarten über JavaScript, obwohl font-display: swap eine gute Browserunterstützung genießt. Mit anderen Worten: Zach empfiehlt FOUT with Class gegenüber @font-face + font-display: swap.
Er empfiehlt FOUT with Class aus diesen drei Gründen:
- Wir können Repaints gruppieren.
- Wir können uns an Benutzereinstellungen anpassen.
- Wir können das Laden von Schriftarten ganz überspringen, wenn Benutzer eine langsame Verbindung haben.
Ich überlasse es Ihnen, sich eingehender mit den Gründen in einem anderen Artikel zu befassen. Beim Schreiben dieses Artikels habe ich einen *vierten* Grund gefunden, FOUT with Class zu bevorzugen: Wir können das Laden von Schriftarten überspringen, wenn Benutzer die Schriftart bereits in ihrem System geladen haben. (Dies tun wir mit sessionStorage, wie wir unten sehen werden.)
FOUT mit Klasse (für Cloud-gehostete Schriftarten)
Zuerst laden wir unsere Schriftarten wie gewohnt von Ihrem Cloud-Hosting-Unternehmen. Hier ist ein Beispiel, bei dem ich Lato von Google Fonts geladen habe
<head>
<link
href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
/>
</head>
Als Nächstes möchten wir Schriftarten über JavaScript laden. Wir fügen ein script in den <head>-Bereich ein, da der Code-Footprint klein ist und es sowieso asynchron sein wird.
<head>
<link
href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
/>
<script src="js/load-fonts.js"></script>
</head>
In load-fonts.js wollen wir die CSS Font Loading API verwenden, um die Schriftart zu laden. Hier können wir Promise.all verwenden, um alle Schriftarten gleichzeitig zu laden. Wenn wir dies tun, gruppieren wir Repaints.
Der Code sieht so aus
if ('fonts' in document) {
Promise.all([
document.fonts.load('1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => () {
document.documentElement.classList.add('fonts-loaded')
})
}
Wenn die Schriftarten geladen sind, wollen wir den Body-Text in die Web-Schriftart ändern. Dies können wir über CSS tun, indem wir die Klasse .fonts-loaded verwenden.
/* System font before [[webfont]]s get loaded */
body {
font-family: sans-serif;
}
/* Use [[webfont]] when [[webfont]] gets loaded*/
.fonts-loaded body {
font-family: Lato, sans-serif;
}
Achten Sie hier darauf: Wir müssen mit diesem Ansatz die Klasse .fonts-loaded verwenden.
Wir können die Web-Schriftart nicht direkt in der font-family des <body> schreiben; dies würde dazu führen, dass Schriftarten heruntergeladen werden, was bedeutet, dass Sie @font-face + font-display: swap verwenden. Es bedeutet auch, dass das JavaScript redundant ist.
/* DO NOT DO THIS */
body {
font-family: Lato, sans-serif;
}
Wenn Benutzer zusätzliche Seiten auf der Website besuchen, haben sie die Schriftarten bereits in ihrem Browser geladen. Wir können den Ladevorgang von Schriftarten überspringen (um die Geschwindigkeit zu erhöhen), indem wir sessionStorage verwenden.
if (sessionStorage.fontsLoaded) {
document.documentElement.classList.add('fonts-loaded')
} else {
if ('fonts' in document) {
Promise.all([
document.fonts.load('1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => () {
document.documentElement.classList.add('fonts-loaded')
})
}
}
Wenn wir das JavaScript zur besseren Lesbarkeit optimieren wollen, können wir ein "Early Return"-Muster verwenden, um die Einrückung zu reduzieren.
function loadFonts () {
if (sessionStorage.fontsLoaded) {
document.documentElement.classList.add('fonts-loaded')
return
}
if ('fonts' in document) {
Promise.all([
document.fonts.load('1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => () {
document.documentElement.classList.add('fonts-loaded')
})
}
loadFonts()
FOUT mit Klasse (für selbst gehostete Schriftarten)
Zuerst laden wir unsere Schriftarten wie gewohnt über @font-face. Die Eigenschaft font-display: swap ist optional, da wir die Schriftarten über JavaScript laden.
@font-face {
font-family: Lato;
src: url('path-to-lato.woff2') format('woff2'),
url('path-to-lato.woff') format('woff');
}
/* Other @font-face declarations */
Als Nächstes laden wir die Web-Schriftarten über JavaScript.
if ('fonts' in document) {
Promise.all([
document.fonts.load('1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => () {
document.documentElement.classList.add('fonts-loaded')
})
}
Dann wollen wir den Body-Text per CSS in die Web-Schriftart ändern.
/* System font before webfont is loaded */
body {
font-family: sans-serif;
}
/* Use webfont when it loads */
.fonts-loaded body {
font-family: Lato, sans-serif;
}
Schließlich überspringen wir das Laden von Schriftarten bei wiederholten Besuchen.
if ('fonts' in document) {
Promise.all([
document.fonts.load('1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => () {
document.documentElement.classList.add('fonts-loaded')
})
}
CSS Font Loader API vs. FontFaceObserver
Die CSS Font Loader API hat eine ziemlich gute Browserunterstützung, ist aber eine ziemlich zickige API.
Diese Daten zur Browserunterstützung stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 35 | 41 | Nein | 79 | 10 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 10.0-10.2 |
Wenn Sie also ältere Browser (wie IE 11 und früher) unterstützen müssen oder wenn Ihnen die API seltsam und umständlich erscheint, sollten Sie Bramsteins FontFaceObserver verwenden. Er ist super leichtgewichtig, es gibt also keinen großen Nachteil.
Der Code sieht so aus. (Er ist *viel* besser als die CSS Font Loader API).
new FontFaceObserver('lato')
.load()
.then(_ => {
document.documentElement.classList.add('fonts-loaded')
})
Stellen Sie sicher, dass Sie fontfaceobserver.standalone.js verwenden, wenn Sie ihn auf Browsern laden möchten, die Promises nicht unterstützen.
FOFT
FOFT steht für flash of faux text (Aufblitzen von Fälschungstext). Die Idee ist, das Laden von Schriftarten in drei Stufen aufzuteilen:
- Schritt 1: Verwenden Sie eine Fallback-Schriftart, wenn die Web-Schriftarten noch nicht geladen sind.
- Schritt 2: Laden Sie zuerst die römische (auch „Buch“ oder „normal“ genannt) Version der Schriftart. Diese ersetzt den Großteil des Texts. Fett und Kursiv werden vom Browser gefälscht (daher „faux text“).
- Schritt 3: Laden Sie den Rest der Schriftarten.
Hinweis: Zach nennt dies auch Standard FOFT.
Standard FOFT verwenden
Zuerst laden wir die römische Schriftart.
@font-face {
font-family: LatoInitial;
src: url('path-to-lato.woff2') format('woff2'),
url('path-to-lato.woff') format('woff');
unicode-range: U+65-90, U+97-122;
}
.fonts-loaded-1 body {
font-family: LatoInitial;
}
if('fonts' in document) {
document.fonts.load("1em LatoInitial")
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
})
}
Dann laden wir andere Schriftarten.
Achten Sie hier darauf: Wir laden Lato erneut, aber diesmal setzen wir font-family auf Lato statt auf LatoInitial.
/* Load this first */
@font-face {
font-family: LatoInitial;
src: url('path-to-lato.woff2') format('woff2'),
url('path-to-lato.woff') format('woff');
unicode-range: U+65-90, U+97-122;
}
/* Load these afterwards */
@font-face {
font-family: Lato;
src: url('path-to-lato.woff2') format('woff2'),
url('path-to-lato.woff') format('woff');
unicode-range: U+65-90, U+97-122;
}
/* Other @font-face for different weights and styles*/
.fonts-loaded-1 body {
font-family: LatoInitial;
}
.fonts-loaded-2 body {
font-family: Lato;
}
if ('fonts' in document) {
document.fonts.load('1em LatoInitial')
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
Promise.all([
document.fonts.load('400 1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => {
document.documentElement.classList.add('fonts-loaded-2')
})
})
}
Auch hier können wir es für wiederholte Ansichten optimieren.
Hier können wir fonts-loaded-2 direkt zum <html> hinzufügen, da die Schriftarten bereits geladen sind.
function loadFonts () {
if (sessionStorage.fontsLoaded) {
document.documentElement.classList.add('fonts-loaded-2')
return
}
if ('fonts' in document) {
document.fonts.load('1em Lato')
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
Promise.all([
document.fonts.load('400 1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => {
document.documentElement.classList.add('fonts-loaded-2')
// Optimization for Repeat Views
sessionStorage.fontsLoaded = true
})
})
}
}
Critical FOFT
Das „Critical“-Teil kommt von „critical css“ (glaube ich) – wo wir nur wesentliches CSS laden, bevor wir den Rest laden. Das tun wir, weil es die Leistung verbessert.
Wenn es um Typografie geht, sind die einzigen kritischen Dinge die Buchstaben A bis Z (sowohl Groß- als auch Kleinbuchstaben). Wir können ein Subset dieser Schriftarten mit unicode-range erstellen.
Wenn wir dieses Subset erstellen, können wir auch eine separate Schriftdatei mit den notwendigen Zeichen erstellen.
So sieht die Deklaration von @font-face aus:
@font-face {
font-family: LatoSubset;
src: url('path-to-optimized-lato.woff2') format('woff2'),
url('path-to-optimized-lato.woff') format('woff');
unicode-range: U+65-90, U+97-122;
}
Wir laden dieses Subset zuerst.
.fonts-loaded-1 body {
font-family: LatoSubset;
}
if('fonts' in document) {
document.fonts.load('1em LatoSubset')
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
})
}
Und wir laden andere Schriftdateien später.
.fonts-loaded-2 body {
font-family: Lato;
}
if ('fonts' in document) {
document.fonts.load('1em LatoSubset')
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
Promise.all([
document.fonts.load('400 1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => {
document.documentElement.classList.add('fonts-loaded-2')
})
})
}
Auch hier können wir es für wiederholte Ansichten optimieren.
function loadFonts () {
if (sessionStorage.fontsLoaded) {
document.documentElement.classList.add('fonts-loaded-2')
return
}
if ('fonts' in document) {
document.fonts.load('1em LatoSubset')
.then(_ => {
document.documentElement.classList.add('fonts-loaded-1')
Promise.all([
document.fonts.load('400 1em Lato'),
document.fonts.load('700 1em Lato'),
document.fonts.load('italic 1em Lato'),
document.fonts.load('italic 700 1em Lato')
]).then(_ => {
document.documentElement.classList.add('fonts-loaded-2')
// Optimization for Repeat Views
sessionStorage.fontsLoaded = true
})
})
}
}
Critical FOFT-Varianten
Zach schlug zwei zusätzliche Critical FOFT-Varianten vor:
- Critical FOFT mit Data URI
- Critical FOFT mit Preload
Critical FOFT mit Data URIs
In dieser Variante laden wir die kritische Schriftart (die subsetted römische Schriftart) mit Data URIs anstelle eines normalen Links. So sieht es aus. (Und es ist beängstigend.)
@font-face {
font-family: LatoSubset;
src: url("data:application/x-font-woff;charset=utf-8;base64,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") format("woff");
/* ... */
}
Dieser Code sieht beängstigend aus, aber es gibt keinen Grund zur Angst. Der schwierigste Teil hier ist die Generierung der Data URI, und CSS-Tricks hilft uns dabei.
Critical FOFT mit Preload
In dieser Variante fügen wir einen Link mit dem preload-Tag zur kritischen Schriftartdatei hinzu. So sieht es aus
<link rel="preload" href="path-to-roman-subset.woff2" as="font" type="font/woff2" crossorigin>
Wir sollten hier nur eine Schriftart vorladen. Wenn wir mehr als eine laden, können wir die anfängliche Ladezeit negativ beeinflussen.
In der Strategieliste erwähnte Zach auch, dass er die Verwendung einer Data URI gegenüber der preload-Variante bevorzugt. Er bevorzugt sie nur, weil die Browserunterstützung für preload früher schlecht war. Heute bin ich der Meinung, dass die Browserunterstützung gut genug ist, um Preloading gegenüber einer Data URI zu bevorzugen.
Diese Daten zur Browserunterstützung stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 50 | 85 | Nein | 79 | 11.1 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 11.3-11.4 |
Abschließender Hinweis von Zach
Chris hat diesen Artikel über Zach laufen lassen und Zach wünschte, er hätte in seinem Originalartikel einem JavaScript-freien Ansatz Priorität eingeräumt.
Ich denke, der Artikel ist gut, aber ich denke, mein Artikel, auf dem er basiert, ist wahrscheinlich in ein paar Punkten etwas veraltet. Ich wünschte, er hätte No-JS-Ansätzen mehr Priorität eingeräumt, wenn man nur ein oder zwei Schriftdateien verwendet (oder mehr, aber nur 1 oder 2 pro Schriftart). JS-Ansätze sind heutzutage eher die Ausnahme, denke ich (es sei denn, Sie verwenden *sehr viele* Schriftdateien oder einen Cloud-Anbieter, der
font-display: swapnicht unterstützt)
Dies ändert das Urteil geringfügig, was ich im nächsten Abschnitt zusammenfassen werde.
Welche Strategie zum Laden von Schriftarten verwenden?
Wenn Sie einen Cloud-Hosting-Anbieter verwenden
- Verwenden Sie
font-display: swap, wenn der Host es bereitstellt. - Andernfalls verwenden Sie FOUT with Class.
Wenn Sie Ihre Web-Schriftarten selbst hosten, haben Sie mehrere Möglichkeiten:
@font-face+font-display: swap- FOUT with Class
- Standard FOFT
- Critical FOFT
Hier erfahren Sie, wie Sie zwischen ihnen wählen:
- Wählen Sie
@font-face+font-display: swap, wenn Sie gerade erst anfangen und sich nicht mit JavaScript herumschlagen wollen. Es ist die einfachste aller Optionen. Wählen Sie diese Option auch, wenn Sie nur wenige Schriftdateien (weniger als zwei Dateien) pro Schriftart verwenden. - Wählen Sie Standard FOFT, wenn Sie bereit sind, JavaScript zu verwenden, aber nicht die zusätzliche Arbeit des Subsetten der römischen Schriftart leisten möchten.
- Wählen Sie eine Critical FOFT-Variante, wenn Sie alles für die Leistung tun wollen.
Das ist alles! Ich hoffe, Sie fanden das nützlich!
Wenn Ihnen dieser Artikel gefallen hat, könnten Ihnen auch andere von mir geschriebene Artikel gefallen. Abonnieren Sie meinen Newsletter 😉. Fühlen Sie sich auch frei, mich zu kontaktieren, wenn Sie Fragen haben. Ich werde mein Bestes tun, um zu helfen!
Bezüglich des Vorschlags FOUT with Class habe ich einige Einwände.
1. Zu Repaints: Es ist ein bisschen pedantisch, aber sicher, Schriftarten werden unterschiedlich schnell geladen, also gebe ich Ihnen das.
2 und 3. Benutzereinstellungen / langsame Verbindung: Dies kann mit der Media Query `prefers-reduced-data` (noch geringe Browserunterstützung) behandelt werden.
Der vierte Punkt bezüglich des Ladens lokaler Schriftarten kann mit dem "local"-Attribut in Ihrer Font-Face-Deklaration behandelt werden. Zum Beispiel:
Diese Vorschläge scheinen im Grunde gegen den Browser zu kämpfen, was wahrscheinlich nicht notwendig ist.
Ich meine nicht, dass Sie diese Dinge NICHT tun SOLLTEN – schließlich geht es in dem Artikel um die absolut beste Leistung, die Sie aus dem Laden von Schriftarten herausholen können. Meine Punkte sind eher aus der Perspektive der Entwicklererfahrung.
Sie haben vergessen, `sessionStorage.fontsLoaded` tatsächlich zu setzen, wenn Sie die Schriftarten laden...
Außerdem sind die Definitionen von LatoInitial und Lato identisch, daher bin ich mir nicht sicher, warum wir zwischen ihnen wechseln.
Schließlich bevorzuge ich selbst `font-display: swap`. Etwaige Fehler darin sind Aufgabe des Browsers zu beheben, nicht meine, und es funktioniert ohne JS – was keine Ihrer anderen Strategien tut.
Danke, dass Sie auf die fehlende `sessionStorage.setItem("fontsLoaded", 1);`-Anweisung hingewiesen haben. Ich habe mich gefragt, wie das gesetzt wird!
Das Laden mit JS beschleunigt das Laden von Schriftarten, da es vor dem Laden des DOMs starten kann, während `font-display: swap` es danach lädt. Dies stellt sicher, dass die Schriftart nicht geladen wird, wenn sie im DOM nicht verwendet wird.
Aber eine JS-freie Version davon wäre großartig (z. B. `font-display: swap eager`?), da stimme ich zu.
Sora hat Recht bezüglich der doppelten Schriftartendeklaration. Wenn Sie sich Zach Leathermans Demo-Code ansehen, tut er das nicht.
Nur so am Rande: Ich habe ein WordPress-Plugin geschrieben, das bei der Implementierung von Zachs bevorzugtem Rezept zum Laden von Web-Schriftarten hilft. Suchen Sie im Plugin-Verzeichnis nach "WP FOFT Loader", wenn Sie es ausprobieren möchten.
Danke für diese Zusammenfassung — ich verfolge Zachs hervorragenden Blog-Post seit Jahren mit all seinen Updates, und ich bin so froh, dass die Font Loading API mittlerweile für die meisten Zwecke gut genug ist (aber gute alte FontFaceObserver und andere JS-Workarounds können immer noch dazu dienen, Dinge zu patchen, wo bessere Leistung oder Unterstützung benötigt wird). Ein solch verwirrendes Thema!
Ich hoffe auch, dass einige dieser Techniken weniger relevant werden, wenn variable Schriftarten weiter verbreitet sind. Die Bereitstellung einer optimierten Web-Schriftart ist viel schöner, als separate Downloads für jede Variante in eine Warteschlange stellen zu müssen.
Wie Sora2455 bereits erwähnt hat, enthalten die Codebeispiele in diesem Beitrag kleinere Fehler, die, wie sie geschrieben sind, dazu führen würden, dass sie nicht wirklich hilfreich sind.
Alle Beispiele mit
sessionStorage.fontsLoadedmüssen diese Eigenschaft tatsächlich imthen()-Methoden auftruesetzen, sonst werden diese Bedingungen niemals erreicht und Schriftarten werden bei jedem nachfolgenden Seitenaufruf weiterhin geladen. (Ich habe das versehentlich auf einer Produktionsseite gemacht und es eine ganze Weile nicht bemerkt! Ugh!)Das Beispiel für *Standard FOFT* mit
LatoInitialundLatowäre nur sinnvoll, wenn zusätzlicheLato-Referenzen für andere Gewichte und Stile hinzugefügt würden — vielleicht sollten diese dem Beispiel hinzugefügt werden, damit dieser Abschnitt einen verständlichen Zweck hat?Es könnte auch erwähnenswert sein, dass viele Web-Schriftartenlizenzen Modifikationen wie Subsetten und vielleicht sogar die Konvertierung aus dem vom Foundry bereitgestellten Format verbieten (z. B. die Konvertierung einer .otf in .woff2 mit FontSquirrel oder
fonttools), was je nachdem, was der Leser tun möchte, eine Überlegung sein könnte...Wenn Sie die Methode "FOUT with Class" verwenden, macht es dann Sinn, die Schriftart auch vorzuladen?
Hat jemand Erfolg mit der Reduzierung von CLS durch die Verwendung von Typekit-Schriftarten und display: swap? Wie im Artikel erwähnt, empfiehlt Adobe jetzt die Verwendung ihrer CSS-Methode, sodass es keine `wf-loaded`-Klasse mehr gibt, mit der man arbeiten kann. Ich habe die Option `display: swap` aktiviert, aber natürlich haben die Fallback-Schriftarten und die geladenen Schriftarten unterschiedliche Zeilenhöhen, so dass CLS immer wieder auftaucht.
Nur 2 Tippfehler für zukünftige Besucher beheben