Font Loading Strategien: FOIT, FOUT und Subsetting
AI generated
{ }
@
CSS · Font Loading · Web Performance
Font Loading Strategien: FOIT, FOUT und Subsetting
Web-Fonts ohne sichtbares Flackern laden

Ein falsch konfiguriertes Font Loading zeigt entweder unsichtbaren Text während des Ladens oder einen sichtbaren Schriftwechsel samt Layout-Sprung, sobald die Web-Font eintrifft. Mit der richtigen Kombination aus font-display, Preload und Subsetting lässt sich beides vermeiden, ohne auf individuelle Typografie zu verzichten.

15 Min. Lesezeit font-display · Preload · Unicode-Range · Variable Fonts WOFF2 · Chrome · Firefox · Safari

1. FOIT und FOUT: zwei Symptome desselben Problems

Beim Font Loading im Web treten historisch zwei unterschiedliche, unerwünschte Effekte auf. FOIT, Flash of Invisible Text, bezeichnet die Situation, in der Text komplett unsichtbar bleibt, bis die Web-Font vollständig geladen ist, weil der Browser standardmäßig bis zu drei Sekunden mit dem Rendern wartet, bevor er auf eine Fallback-Schrift zurückgreift. FOUT, Flash of Unstyled Text, bezeichnet das Gegenteil: der Text erscheint sofort in einer Fallback-Schrift und springt sichtbar um, sobald die eigentliche Web-Font eintrifft, oft begleitet von einer Layout-Verschiebung, weil unterschiedliche Schriften unterschiedliche Zeichenbreiten haben.

Beide Effekte sind Symptome desselben zugrunde liegenden Problems: der Browser muss eine Entscheidung treffen, was er zeigt, während eine externe Font-Datei noch über das Netzwerk lädt. Ein durchdachtes Font Loading-Konzept behandelt dieses Zeitfenster nicht als unvermeidbares Übel, sondern als gestaltbaren Prozess, in dem gezielt entschieden wird, wann welche Schrift angezeigt wird und wie der Übergang zur endgültigen Web-Font möglichst unauffällig gestaltet werden kann. Die folgenden Abschnitte zeigen die einzelnen Bausteine dieser Strategie im Detail.

2. font-display: die fünf Werte im Detail

Die CSS-Eigenschaft font-display innerhalb einer @font-face-Regel ist der zentrale Hebel für Font Loading und definiert, wie der Browser den Zeitraum zwischen Seitenaufbau und vollständigem Laden der Web-Font behandelt. Der Wert block erzeugt klassisches FOIT: bis zu drei Sekunden unsichtbarer Text, danach Fallback, mit anschließendem Austausch sobald die Web-Font eintrifft. Der Wert swap erzeugt klassisches FOUT: sofortige Anzeige in der Fallback-Schrift, praktisch unbegrenzte Wartezeit auf den Austausch zur Web-Font.

Der Wert fallback ist ein Kompromiss: eine sehr kurze Blockierungsphase von etwa hundert Millisekunden, gefolgt von einem kurzen Austauschfenster von wenigen Sekunden, nach dessen Ablauf dauerhaft bei der Fallback-Schrift geblieben wird, selbst wenn die Web-Font später noch eintrifft. Der Wert optional geht noch einen Schritt weiter: ebenfalls eine kurze Blockierungsphase, aber kein Austausch mehr danach, wenn die Web-Font zu diesem Zeitpunkt noch nicht verfügbar ist, was besonders für wiederkehrende Besucher mit warmem Cache sinnvoll ist, weil die Font dann meist längst geladen ist. Der Standardwert auto überlässt das Verhalten dem Browser, was in der Praxis meist block entspricht und deshalb selten die beste Wahl ist.


/* font-display comparison for the same web font */
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-variable.woff2") format("woff2-variations");
  font-display: swap; /* immediate fallback text, swap when font arrives */
  font-weight: 100 900;
}

/* optional: best for repeat visits, avoids any layout shift on cache hit */
@font-face {
  font-family: "Inter Optional";
  src: url("/fonts/inter-variable.woff2") format("woff2-variations");
  font-display: optional;
  font-weight: 100 900;
}

3. Preload: die Font-Anfrage vorziehen

Ohne zusätzliche Hinweise entdeckt der Browser eine Web-Font-Datei erst, nachdem er das CSS geparst und die zugehörige @font-face-Regel als tatsächlich benötigt erkannt hat, oft erst nachdem das Layout bereits berechnet wurde und feststeht, welche Zeichen überhaupt gerendert werden müssen. <link rel="preload" as="font" type="font/woff2" crossorigin> im <head> verschiebt diese Entdeckung deutlich nach vorne, indem der Browser die Font-Datei parallel zum CSS anfordert, statt sequenziell darauf zu warten.

Der Effekt von Preload auf Font Loading ist besonders bei font-display: swap spürbar: je früher die Font-Datei zu laden beginnt, desto kürzer das Zeitfenster, in dem die Fallback-Schrift sichtbar bleibt, und desto seltener tritt der sichtbare Austausch überhaupt in Erscheinung. Wichtig ist, das Attribut crossorigin auch bei Fonts von der eigenen Domain zu setzen, weil Font-Requests laut Spezifikation immer im anonymen CORS-Modus erfolgen, ein fehlendes crossorigin führt zu einer doppelten Anfrage, weil der Browser den vorgeladenen Request nicht dem tatsächlichen CSS-Request zuordnen kann.


<head>
  <!-- Preload the primary font file so it starts downloading
       in parallel with the CSS, not after it -->
  <link rel="preload" href="/fonts/inter-variable.woff2"
        as="font" type="font/woff2" crossorigin>
  <link rel="stylesheet" href="/css/fonts.css">
</head>

4. Unicode-Range-Subsetting für kleinere Dateien

Eine vollständige Web-Font-Datei enthält oft mehrere tausend Glyphen für Sprachen, kyrillische und griechische Zeichen sowie Sonderzeichen, die auf einer deutschen oder englischen Website niemals verwendet werden. unicode-range innerhalb der @font-face-Regel teilt dem Browser mit, für welchen Zeichenbereich eine bestimmte Font-Datei zuständig ist, sodass der Browser nur die Dateien herunterlädt, die für den tatsächlich auf der Seite vorkommenden Text benötigt werden.

Ein typisches Subsetting für eine westeuropäische Website trennt lateinische Basiszeichen von lateinischen Erweiterungszeichen wie Umlauten und Akzenten, wodurch die für den Großteil des Texts benötigte Datei deutlich kleiner ausfällt als eine Datei mit dem vollständigen Zeichensatz. Für Font Loading bedeutet das direkt kürzere Ladezeiten, weil eine kleinere Datei schneller über das Netzwerk übertragen wird, was wiederum das Zeitfenster für FOIT oder FOUT verkürzt, unabhängig davon, welcher font-display-Wert gewählt wurde.


/* Subsetting: only load the glyph ranges actually used on the page */
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153; /* basic Latin */
  font-display: swap;
}

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF; /* Latin Extended, e.g. umlauts */
  font-display: swap;
}

5. size-adjust und Fallback-Font-Metriken angleichen

Selbst mit optimalem font-display bleibt bei swap und fallback das Risiko einer Layout-Verschiebung bestehen, weil die Fallback-Schrift und die Web-Font meist unterschiedliche Zeichenbreiten und Zeilenhöhen haben. Die CSS-Deskriptoren size-adjust, ascent-override, descent-override und line-gap-override innerhalb einer @font-face-Regel für die Fallback-Schrift erlauben es, deren Metriken so anzupassen, dass sie der Web-Font möglichst genau entsprechen.

Diese Technik, oft als Font-Metrik-Überschreibung bezeichnet, definiert eine zusätzliche @font-face-Regel für eine bereits systemseitig verfügbare Fallback-Schrift wie Arial, mit angepassten Metrik-Deskriptoren, und weist dieser angepassten Version einen eigenen font-family-Namen zu, der in der Fallback-Kette vor der eigentlichen Web-Font steht. Werkzeuge wie der Font Style Matcher von Google oder das npm-Paket fontaine berechnen die notwendigen Werte automatisch, indem sie die Metriken beider Schriften vergleichen und die passenden Prozentwerte für size-adjust ermitteln, wodurch der sichtbare Sprung beim Font-Austausch auf ein Minimum reduziert wird.

6. Variable Fonts als Ladestrategie

Ein oft übersehener Hebel für effizientes Font Loading ist der Einsatz von Variable Fonts anstelle mehrerer statischer Schriftschnitte. Eine klassische Schriftfamilie mit vier Schnitten, Regular, Bold, Italic und Bold Italic, erfordert vier separate Font-Dateien und damit vier separate Netzwerk-Requests. Eine Variable-Font-Datei enthält alle Gewichte und Stile in einer einzigen Datei, adressierbar über die CSS-Eigenschaft font-variation-settings oder die Kurzschreibweise im font-weight-Bereich.

Für Font Loading bedeutet das: statt vier Font-Requests mit jeweils eigenem FOIT- oder FOUT-Fenster genügt ein einziger Request, der alle benötigten Gewichte gleichzeitig verfügbar macht. Die Gesamtdateigröße einer Variable-Font-Datei liegt zwar über der einer einzelnen statischen Datei, aber meist deutlich unter der Summe aller benötigten statischen Schnitte, insbesondere wenn eine Seite mehr als zwei Gewichte gleichzeitig verwendet, was bei modernen Typografie-Systemen mit feinen Abstufungen zwischen Regular, Medium und Semibold häufig der Fall ist.

7. Selbst-Hosting vs. Google Fonts und andere CDNs

Fonts über ein Drittanbieter-CDN wie Google Fonts einzubinden bedeutet, dass der Browser eine zusätzliche DNS-Auflösung und Verbindung zu einer fremden Domain aufbauen muss, bevor die eigentliche Font-Datei überhaupt angefragt werden kann. Dieser zusätzliche Verbindungsaufbau kostet insbesondere auf mobilen Netzwerken mit hoher Latenz spürbare Zeit und verlängert das Zeitfenster, in dem FOIT oder FOUT sichtbar sind, unabhängig von der gewählten font-display-Strategie.

Selbst-Hosting der Web-Font-Dateien auf der eigenen Domain eliminiert diese zusätzliche Verbindung vollständig und ermöglicht zusätzlich die Nutzung von rel="preload", das bei Fonts von fremden Domains aufgrund fehlender Kontrolle über Cache-Header und Verbindungsverhalten weniger zuverlässig funktioniert. Für Projekte mit strengen Performance-Anforderungen, etwa im Kontext von Core Web Vitals, ist Selbst-Hosting deshalb praktisch immer die bessere Wahl, auch wenn Google Fonts durch die eigene Update-Pflege bequemer erscheint.

8. Messen: CLS, LCP und die Font-Loading-API

Der wichtigste messbare Effekt von unzureichendem Font Loading ist Cumulative Layout Shift, sichtbar in Chrome DevTools über die Layout-Shift-Regionen im Rendering-Tab oder programmatisch über PerformanceObserver mit dem Eintragstyp layout-shift. Ein Sprung von mehr als 0,1 CLS-Punkten direkt nach dem Font-Austausch deutet stark auf unzureichend angepasste Fallback-Metriken hin und rechtfertigt eine Überprüfung der size-adjust-Konfiguration aus dem vorherigen Abschnitt.

Die native document.fonts-API, auch CSS Font Loading API genannt, erlaubt zusätzlich eine programmatische Kontrolle über den Ladezustand: document.fonts.ready löst auf, sobald alle deklarierten Fonts geladen sind, und document.fonts.check() prüft synchron, ob eine bestimmte Font zu einem gegebenen Zeitpunkt bereits verfügbar ist. Diese API eignet sich gut, um gezielt eine CSS-Klasse zu setzen, sobald die Web-Font tatsächlich geladen ist, etwa um während des Ladens eine kontrolliert reduzierte, aber stabile Typografie anzuzeigen, statt dem Browser-Standardverhalten zu vertrauen.


// Track font loading state to add a class once fonts are ready,
// useful for coordinating fallback-to-webfont transitions manually
document.fonts.ready.then(() => {
  document.documentElement.classList.add("fonts-loaded");
});

// Check synchronously whether a specific font is already available
if (document.fonts.check("16px Inter")) {
  console.log("Inter is already loaded and cached");
}

// Measure layout shifts potentially caused by font swaps
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log(`Layout shift value: ${entry.value}`);
    }
  }
}).observe({ type: "layout-shift", buffered: true });

9. Strategien im direkten Vergleich

Die folgende Tabelle stellt die vorgestellten Font Loading Strategien gegenüber, um die Auswahl für ein konkretes Projekt zu erleichtern.

Strategie Löst Aufwand Empfehlung
font-display: swap FOIT vermeiden Sehr gering Fast immer als Basis sinnvoll
Preload FOUT-Fenster verkürzen Gering Für die primäre Schrift immer setzen
Unicode-Range-Subsetting Dateigröße reduzieren Mittel Bei mehrsprachigen Zeichensätzen wichtig
size-adjust Metrik-Override Layout-Verschiebung minimieren Mittel Für strenge CLS-Ziele empfohlen
Variable Fonts Mehrere Requests bündeln Mittel Bei mehr als zwei Schriftschnitten
Selbst-Hosting Verbindungsaufbau eliminieren Mittel bis hoch Für strenge Performance-Budgets

Der praktische Weg für die meisten Projekte kombiniert mehrere Zeilen dieser Tabelle: font-display: swap als Basis, kombiniert mit Preload für die wichtigste Schriftdatei, Unicode-Range-Subsetting bei mehrsprachigen Inhalten und einer Metrik-Anpassung der Fallback-Schrift, sobald CLS-Messungen eine spürbare Layout-Verschiebung beim Font-Austausch zeigen. Selbst-Hosting und Variable Fonts sind die aufwendigeren, aber langfristig lohnenden Schritte für Projekte mit strengen Performance-Zielen.

Mironsoft

CSS-Performance, Rendering-Optimierung und moderne Web-Frontends

Web-Fonts ohne Flackern und Layout-Sprung?

Wir konfigurieren font-display, Preload, Unicode-Range-Subsetting und Fallback-Metriken passend zu eurer Typografie und messen den Effekt anhand von CLS und LCP vor und nach der Umstellung.

Font-Audit

Analyse bestehender Font-Requests, Subsetting-Potenzial und CLS-Ursachen

Implementierung

Preload, Subsetting und Metrik-Override sauber in bestehende Builds integrieren

Messung

Vorher-Nachher-Vergleich von CLS und LCP mit Lighthouse und Core Web Vitals

10. Zusammenfassung

Erfolgreiches Font Loading vermeidet sowohl FOIT als auch FOUT, indem es das Zeitfenster zwischen Seitenaufbau und verfügbarer Web-Font aktiv gestaltet, statt es dem Browser-Standardverhalten zu überlassen. font-display: swap in Kombination mit rel="preload" bildet die Basis für die meisten Projekte, Unicode-Range-Subsetting reduziert die zu ladende Dateigröße bei mehrsprachigen Zeichensätzen erheblich, und Metrik-Overrides über size-adjust minimieren die Layout-Verschiebung beim Austausch der Fallback-Schrift.

Variable Fonts bündeln mehrere Schriftschnitte in einer Datei und reduzieren so die Anzahl paralleler Font-Requests, während Selbst-Hosting den zusätzlichen Verbindungsaufbau zu Drittanbieter-CDNs eliminiert. Wer den Effekt seiner Font Loading Strategie belegen will, misst Cumulative Layout Shift und nutzt die native document.fonts-API, um den Ladezustand programmatisch zu überwachen und gezielt darauf zu reagieren.

Font Loading Strategien: Das Wichtigste auf einen Blick

FOIT vs. FOUT

Unsichtbarer Text versus sichtbarer Schriftwechsel, beides Symptome desselben Ladezeit-Problems.

Basis-Konfiguration

font-display: swap plus rel="preload" für die primäre Web-Font.

Dateigröße

Unicode-Range-Subsetting und Variable Fonts reduzieren Ladezeit und Request-Anzahl.

Layout-Stabilität

size-adjust Metrik-Override minimiert Cumulative Layout Shift beim Font-Austausch.

11. FAQ: Font Loading Strategien

1Unterschied zwischen FOIT und FOUT?
FOIT zeigt unsichtbaren Text, FOUT zeigt sofort Fallback-Text mit sichtbarem Austausch später.
2Welcher font-display-Wert als Standard?
swap für die meisten Fälle, optional für wiederkehrende Besucher mit warmem Cache.
3Warum ist Preload wichtig?
Lädt die Font-Datei parallel zum CSS statt erst danach, verkürzt das Fallback-Fenster.
4Was bewirkt Unicode-Range-Subsetting?
Teilt Fonts nach Zeichenbereich auf, lädt nur tatsächlich benötigte Bereiche.
5Wie Layout-Verschiebung verhindern?
Mit size-adjust und verwandten Deskriptoren, um Fallback-Metriken anzugleichen.
6Vorteil von Variable Fonts?
Alle Gewichte in einer Datei statt mehrerer separater Requests.
7Google Fonts selbst hosten?
Ja bei strengen Performance-Zielen, eliminiert Verbindungsaufbau zu fremder Domain.
8Wie messe ich die Layout-Verschiebung?
Mit Cumulative Layout Shift über DevTools oder PerformanceObserver.
9Was macht die document.fonts-API?
Erlaubt programmatische Kontrolle über den Ladezustand von Fonts.
10Braucht Preload crossorigin?
Ja, Font-Requests laufen immer im anonymen CORS-Modus, auch bei eigenen Domains.