Webfonts haben mehrere Optimierungs-Dimensionen, die in typischen Online-Shops gleichzeitig daneben liegen: zu viele Schriftschnitte, einzelne Dateien zu groß, Schriften vom fremden Origin mit eigenem Verbindungs-Aufbau, und der Browser-Cache hilft seit Chrome 86 nicht mehr über Domain-Grenzen hinweg.
Jeder dieser Punkte ist verschwenderisch und kostet Ladezeit. Und Ladezeit kostet Conversion Rate.
Messungen aus einem echten Audit:
5 TTF-Dateien, 639 KB Webfont-Ballast, 300 ms LCP-Anteil.
Nach Optimierung: 288 KB, 0 ms LCP-Anteil durch Webfonts.
Was du hier liest:
- Wie der Browser Schriften lädt und warum das auf den ersten Render-Frame durchschlägt
- Welche Optimierungs-Hebel echten Effekt haben, sortiert nach Impact
- Wo Anti-Patterns als „Optimierung“ verkauft werden
- Build-Pipeline für Vanilla-Setup, Framework-Defaults und Plattform-Hinweise
- Audit-Snapshot aus einer realen Messung, anonymisiert
tl;dr: die acht Hebel in der Reihenfolge ihres Impacts.
- 30-50% einsparen durch WOFF2 anstatt TTF/OTF
- Nutze Self-Hosting anstatt Third-Party CDNs
- Maximal zwei bis drei Schriftgewichte aktiv halten
- Subsetting auf die Zielsprachen plus eine Allow-List für Eigennamen, für DACH typischerweise
Basic LatinplusLatin-1 SupplementplusLatin Extended-A font-display: optionalfür Body,swapfür Headlines, niemalsblockoderauto- Verwende Preloads nur für die ein bis zwei Schnitte, die Above-the-fold gerendert werden
- Fallback-Metric-Overrides (
size-adjust,ascent-override) gegen CLS beim Schriftwechsel Cache-Control: max-age=31536000, immutablefür Schriftdateien mit Cachebreaker im Dateinamen
- Warum verzögern Webfonts den ersten Eindruck?
- Was kostet eine Webfont im Shop wirklich?
- Was du schon in der Designphase entscheiden kannst
- Self-Hosting oder Google Fonts: was ist schneller?
- WOFF2 reicht als einziges Schriftformat
- Welche Glyphen lädst du wirklich?
- Preload: vorsichtig statt automatisch
- font-display: optional, swap oder fallback
- Wie verhinderst du Layout-Sprünge?
- Icon-Fonts oder SVG: was ist besser?
- Wie integrierst du Webfonts in den Build?
- So prüfst du, ob es wirklich besser geworden ist
- Häufige Fragen
- Hohe Ladezeiten durch Webfonts?Mein Thema.
Warum verzögern Webfonts den ersten Eindruck?
Webfonts vs. Web-safe Fonts
Web-safe Fonts sind Schriften, die auf den meisten Endgeräten vorinstalliert sind: Arial, Helvetica, Verdana, Georgia, Times New Roman, Courier New, Tahoma. Der Browser zieht sie aus dem Betriebssystem. Sie werden nicht heruntergeladen und haben damit keinen Performance-Effekt.
Webfonts sind das Gegenstück: Schriften, die der Browser per @font-face-Direktive von einem Server herunterlädt, bevor er sie darstellen kann. Genau dieser Download-Schritt ist der Performance-Faktor, um den es im Folgenden geht. Wenn dieser Artikel im weiteren Verlauf von „Schrift laden“ oder „Font-Loading“ spricht, sind immer Webfonts gemeint.
Eine eigene Kategorie ist der CSS-Wert system-ui. Er löst zur OS-Standard-UI-Schrift auf, also keine fest definierte Schrift, sondern was das Betriebssystem als System-Font setzt: San Francisco auf macOS und iOS, Segoe UI Variable auf Windows 11, Roboto auf Android, je nach Distro auch wechselnd auf Linux.
Wie blockiert eine Webfont den Render?
Schriften gehören zum Critical Rendering Path, also zur Kette der Schritte, die der Browser durchlaufen muss, bevor er den ersten Pixel zeichnet. Bevor er einen Buchstaben anzeigt, muss er die Font-Datei geladen, dekodiert und an die Rendering-Pipeline weitergegeben haben. Bis das passiert, hat er drei Optionen:
a) gar nichts anzeigen (FOIT, Flash of Invisible Text) b) den Fallback-Font zeigen und später wechseln (FOUT, Flash of Unstyled Text) c) den Fallback dauerhaft behalten
Welche Option der Browser wählt, lässt sich steuern. Ohne explizite Steuerung warten viele Browser standardmäßig bis zu drei Sekunden, bevor sie auf einen Fallback ausweichen. Auf vielen Shop-Seiten bestimmt der Render-Status der Schrift das LCP-Element (Largest Contentful Paint), etwa Hero-Headline oder Body-Copy oberhalb des sichtbaren Bereichs.
Browser haben FOIT lange als Default gewählt, um einen sichtbaren Schriftwechsel zu vermeiden. Auf langsameren Verbindungen wartet Chrome bis zu 1500 Millisekunden auf Preload-Fonts, bevor er rendert. Das kann den Unterschied zwischen „Seite sichtbar“ und Nutzer verlässt die Seite ausmachen.
Was „Ladezeit“ hier konkret bedeutet
Eine schlecht geladene Webfont zeigt sich an mehreren Stellen gleichzeitig:
- Die Seite bleibt unsichtbar. Mit der Browser-Default-Einstellung wartet der Browser bis zu drei Sekunden auf die Schrift, bevor er Text rendert.
- Die Schrift wird als letztes sichtbar. Wenn der Browser zuerst einen Fallback-Font rendert, sind Bilder, Layout und Buttons früh da. Der Schrift-Look der Marke kommt mit Verzögerung.
- Nach dem Laden der Schriftart springt das Layout. Webfonts haben andere Metriken (Breite, x-Höhe) als Fallback-Schriften. Beim Swap rechnet der Browser das Layout neu durch. Folge: Zeilenumbrüche verschieben sich, CTA-Buttons (Call to Action) rutschen nach unten, Klicks landen daneben.
- Der Schrift-Wechsel lenkt den Besucher ab. Selbst ohne messbaren Layout-Shift zieht der sichtbare Wechsel der Schrift die Aufmerksamkeit auf sich, genau in dem Moment, in dem konzentriert gelesen, geklickt oder über den Kauf nachgedacht werden sollte. CLS (Cumulative Layout Shift) erfasst nur die Verschiebung, nicht die optische Irritation. Die Folge ist eine höhere Bounce-Rate, ohne dass Standard-Metriken den Effekt anzeigen.
Hintergrund: Bram Stein, Webfont Handbook (A Book Apart 2017); Erwin Hofman, Should you preload fonts for performance? (rumvision 2025).
Was kostet eine Webfont im Shop wirklich?

Wie viel das in der Praxis kostet, zeigt ein konkreter Audit aus einem deutschen Juwelier-Shop auf Shopware 6, gemessen Ende April 2026.
Die Übersichtsseite lädt fünf Gewichte Open Sans, alle im ineffektiven TTF-Format. Zusammen 639 KB.
Im CSS steht body { font-family: "Open Sans" } ohne Fallback-Stack. Solange die Schrift fehlt, rendert der Browser Times als Default. Auf Slow-4G entsteht ein FOUT-Window von 283 Millisekunden mit sichtbarem Wechsel von Serif zu Sans-Serif.
Quick-Win-Potenzial
Konvertierung der fünf TTF-Dateien zu WOFF2 reduziert den Transfer in unserer eigenen Messung von 639 KB auf 288 KB. Das sind 54,9% weniger, rund 350 KB Einsparung pro Seitenaufruf. Auf einer mobilen Verbindung mit der Daumenregel „1 MB Download braucht etwa eine Sekunde“ entspricht das rund 300 Millisekunden, um die die Schrift früher gerendert sein kann. Zusätzlich kann das kurze Aufblitzen der Ersatz-Schrift verhindert werden, weil der Browser bei einem ergänzten Fallback-Stack direkt eine passende Sans-Serif rendert statt einer Standard-Serif wie Times.
Was 100 ms in Umsatz bedeuten
Wer die ms in Conversion-Effekt übersetzen will:
Zalando misst per A/B-Test +0,7% Revenue pro 100 ms schnellerer Mobile-Site (Engineering-Blog 2018), eBay +0,5% Add-to-Cart pro 100 ms (web.dev Case Study 2019), Vodafone +8% Sales bei 31% LCP-Verbesserung (web.dev Case Study 2021).
Daumenregel: rund 0,5 bis 0,7% Revenue-Lift pro 100 ms schnellerer Mobile-Site im B2C.
Diese Zahlen stammen aus großen Shops; auf einem DACH-Mittelstands-Shop fällt die Größenordnung ähnlich aus, der exakte Wert braucht eigenes A/B-Testing.
Zeichen für verschwendete Ladezeit
Du verschwendest Ladezeit für Schriften, wenn mindestens eines der folgenden Symptome zutrifft. Jeder Punkt ist für sich ein Optimierungs-Potenzial:
- Eine einzelne Schriftdatei ist größer als 20 KB
- Du lädst mehr als vier Schriftdateien insgesamt
- Mindestens eine Datei liegt nicht im Format WOFF2
- Schriften werden von einem fremden Origin geladen (fonts.gstatic.com, jsdelivr.net oder ähnlich; ein eigener CDN-Origin wie
cdn.shop.deist in Ordnung, weil er bewusst für niedrige Latenz gewählt wurde) - Eine
@font-face-Deklaration im CSS hat keinenfont-display-Wert - Im DevTools-Network-Tab tauchen TTF- oder OTF-Dateien auf
Was du schon in der Designphase entscheiden kannst
Die billigste Optimierung ist die, die nie ins Theme einzieht. Vier Entscheidungen in der Designphase haben mehr Hebel als jede spätere Performance-Runde.
Eine Schriftfamilie reicht meistens
Die Versuchung ist groß: eine Display-Schrift fürs Hero, eine Sans-Serif für Body, eine humanistische Serif für Zitate, eine Mono-Schrift für Preise. Vier Familien, jeweils zwei oder drei Gewichte, schnell zwölf Dateien.
Für Standard-Shops reicht ein gut gewählter Sans-Serif für Hero und Body, mit zwei oder drei Gewichten gibt er auch Hierarchie. Editorial- oder Premium-Brands brauchen häufiger eine Display-Schrift fürs Hero plus eine Body-Sans, zwei Familien sind dann legitim. Das Performance-Budget muss aber bewusst dafür eingerechnet werden.
Brand-vs-Performance-Trade-off
Zwei bis drei Gewichte statt sieben
Webfonts kommen oft mit neun oder mehr Gewichten (Thin, ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold, Black). Das Schriftgewicht ist die Strichstärke und wird per font-weight-Property gesteuert (font-weight: 700 für Bold). Davon zu unterscheiden ist der Schriftschnitt: eine vollständige Variante einer Familie wie „Open Sans Regular Italic“, die font-weight, font-style und font-stretch kombiniert. Im Datei-Budget zählt jeder Schnitt als eigene Datei.
Page-Builder wie Elementor laden gerne alle Gewichte, sobald sie konfiguriert sind. Auf der Live-Seite werden in der Regel Regular und Bold genutzt, manchmal Medium oder SemiBold für Headlines. Der Rest ist Ballast.
Faustregel: Regular plus Bold deckt 80% der Anwendungsfälle. Ein drittes Gewicht für Display ist legitim. Mehr ist eine Design-Entscheidung, die ins Performance-Budget eingerechnet werden muss.
Variable Font als Default-Wahl
Eine Variable Font enthält alle Gewichte einer Familie als Achsen-Definition in einer einzigen Datei. Statt fünf Dateien für Light, Regular, Medium, SemiBold und Bold lädt der Browser eine Datei und interpoliert die Gewichte daraus. Italic kommt über die slnt-Achse hinzu, ebenfalls ohne separate Datei.
Variable Fonts haben verschiedene Achsen. Gewicht (wght) ist die häufigste, aber nicht die einzige:
wght: Strichstärke, typisch 100 bis 900wdth: Breite, von Condensed bis Expandedslnt: Schräge (Slant), deckt Italic ab ohne separate Dateiital: diskreter Italic-Schalter (0 oder 1)opsz: Optical Size, passt das Design an die Render-Größe an
Welche Achsen eine Schrift unterstützt, lässt sich auf wakamaifondue.com prüfen, Drag-and-Drop einer Font-Datei reicht.

Break-Even
Eine Variable Font lohnt sich ab drei oder vier benötigten Schnitten. Inter Variable wiegt rund 340 KB als WOFF2, das statische Inter Regular rund 110 KB. Bei zwei Schnitten (Regular plus Bold) sind die Statics in Summe kleiner. Ab vier Schnitten (Regular, Italic, Bold, Bold Italic) gewinnt die Variable Font mit wght plus slnt-Achse, weil Italic keine eigene Datei kostet.
Variable Fonts haben spezifische Einschränkungen:
- Nicht jede Schrift hat eine Variable-Variante.
Inter,Roboto Flex,Source Sans 3ja.LatoundOpen Sanstypisch nur als statische Schnitte. - Jede zusätzliche Achse erweitert die Datei.
wghtallein ist günstig,wghtpluswdthplusslntplusopszsummiert sich. slntist kein echtes Italic. Die Achse schrägt das Roman-Design mechanisch. Bei Humanist-Schriften (echtes Italic mit eigenen Glyph-Formen, einstöckigema) ist der Unterschied groß.- Hinting und Interpolation sind weniger ausgereift. Bei Render-Größen unter 14px auf Standard-DPI ist der Schärfe-Verlust gegenüber gut gehinteten Statics sichtbar. Zwischenwerte zwischen Master-Positionen (
wght: 550) sind mathematische Interpolation, bei kleineren Foundries sieht das manchmal unsauber aus.
Wann sich eine Variable Font nicht lohnt
Bei nur Regular plus Bold reicht die statische Variante aus. Auch wenn die gewählte Schrift keine Variable-Variante hat und ein Wechsel auf Inter oder Roboto Flex nicht infrage kommt, ist statisch die richtige Wahl.
Self-Hosting oder Google Fonts: was ist schneller?

Steht die Schriftauswahl, kommt die nächste Frage: vom eigenen Server oder vom Google-CDN?
Wer Schriften über Google Fonts CDN einbindet, lädt sie von zwei fremden Origins: erst die CSS-Datei von fonts.googleapis.com, dann die WOFF2-Glyph-Files von fonts.gstatic.com. Beide brauchen einen eigenen Verbindungs-Aufbau (DNS-Lookup, Transport-Verbindung, TLS-Handshake), und das CSS muss vor dem Font-Request erst geparst werden, bevor der Browser überhaupt weiß, welche Glyph-Files er nachladen soll. Beim Erstbesuch summiert sich das auf 200 bis 400 Millisekunden auf Slow-4G, bevor der erste Schrift-Byte über die Leitung geht. Ab dem zweiten Besuch innerhalb von 30 Tagen läuft die Verbindung zwar via HTTP/3 (kombinierter Transport- und Crypto-Handshake in einem Roundtrip), die zwei Cross-Origin-Hops und die serielle CSS→Font-Abhängigkeit bleiben aber bestehen.
Lange galt das als akzeptabler Trade-off: Die Schrift liege ohnehin im Browser-Cache von einer anderen Site, der zweite Aufruf wäre dann kostenlos. Seit dem Cache-Partitioning in Chrome 86 (Oktober 2020) und Firefox 85 (Januar 2021) stimmt das nicht mehr. WebKit hatte schon vorher partitioniertes Caching, getrennt von der bekannteren ITP-Tracking-Schutz-Schicht (Intelligent Tracking Prevention). Der Browser-Cache ist seitdem pro Top-Level-Domain der einbettenden Seite getrennt, Cross-Site-Cache-Hits sind unmöglich. Wer Google Fonts CDN nutzt, lädt sie für jeden Erstbesucher neu, auch wenn dieselbe Datei auf hundert anderen Sites bereits gecacht wäre.
DSGVO-Status DACH
Das Landgericht München I hat am 20. Januar 2022 (Az. 3 O 17493/20) entschieden: die dynamische Einbindung von Google Fonts ohne Einwilligung der Nutzer verstößt gegen die DSGVO. Der Kläger erhielt 100 Euro Schadensersatz. Das Urteil ist rechtskräftig.
Im März 2023 hat dasselbe Gericht (Az. 4 O 13063/22) Massenabmahnungen auf Basis dieses Urteils als rechtsmissbräuchlich eingestuft. Die DSGVO-Frage selbst bleibt damit gültig, aber Abmahnwellen sind kein realistisches Risiko mehr für DACH-Shops.
Im August 2025 hat der Bundesgerichtshof drei Fragen zur Google-Fonts-Thematik dem EuGH vorgelegt (VI ZR 258/24). Die höchstrichterliche Klärung läuft. Bis dahin bleibt das LG-München-Urteil die maßgebliche deutsche Erstinstanz-Entscheidung.
Klare Antwort für DACH-Shops: Self-Hosting ist die sichere Wahl, sowohl aus Performance- als auch aus Compliance-Sicht. Wer heute noch das Google-Fonts-CDN dynamisch einbindet, riskiert einzelne Abmahnungen (auch wenn die Massenabmahn-Welle vorbei ist) und liefert gleichzeitig schlechtere Performance als mit Self-Hosting. Es gibt kein Argument, am CDN festzuhalten.
Self-Hosting in der Praxis
Vier Wege, je nach Stack:
- google-webfonts-helper (gwfh, Web-UI): Schriftname eintippen, Subset und Gewichte auswählen, ZIP mit WOFF2-Dateien plus passender
@font-face-CSS herunterladen. Kein Build-System nötig. - Fontsource (npm-Paket pro Schrift):
npm i @fontsource-variable/interoder@fontsource/open-sans. Subsets per Modul-Import auswählen, Build-System wie Vite oder Webpack bündelt die Dateien automatisch. - OMGF (WordPress-Plugin): Schriften aus dem Theme automatisch self-hosten, mit Subsetting-Optionen.
- Framework-Defaults:
next/font/googlelädt Schriften beim Build, nicht zur Runtime.@nuxt/fontsund Astros experimentellefonts-API erledigen dasselbe.
Harry Roberts hat in Self-host your static assets (CSS Wizardry, 2019) die generelle Argumentation für Self-Hosting jenseits von Schriften gesammelt: weniger Origins, das Caching wird einheitlich, die Performance bleibt kontrollierbar. Sein 3G-Performance-Test fasst es in einem Satz: „Over 3G, the externally-hosted version comes in at an eye-watering 1.765s slower.“
Self-Hosting vs Google Fonts CDN: was ist 2026 schneller?
Self-Hosting ist schneller. Cache-Partitioning seit Chrome 86 hat den theoretischen Cache-Vorteil von Google Fonts aufgehoben. Beim Google-CDN braucht der Browser zwei Cross-Origin-Verbindungen (zu fonts.googleapis.com für das CSS und zu fonts.gstatic.com für die Glyph-Files), und das CSS muss vor dem Font-Request erst geparst werden. Auf Slow-4G ein zusätzlicher Block von 200 bis 400 Millisekunden beim Erstbesuch, bevor die erste Schriftdatei beginnt zu laden. Self-hosted Schriften nutzen die bereits etablierte Connection des Hauptdokuments und werden ab dem zweiten Pageview des Besuchers aus dem Browser-Cache bedient. Performance- und Compliance-Argumente zeigen in dieselbe Richtung.
WOFF2 reicht als einziges Schriftformat
Webfonts gibt es in mehreren Formaten. 2026 ist davon nur eines relevant: WOFF2 (Web Open Font Format 2.0, W3C-Recommendation seit 2018). Browser-Support: rund 97% (caniuse, Stand 2026), inklusive iOS-Safari ab Version 12.
WOFF2 ist aktuell das beste Webfont-Format und rund 30% kleiner als sein Vorgänger WOFF, bei identischer Render-Qualität.
2026 ist WOFF2 die einzige relevante Wahl. WOFF, TTF, OTF, EOT und SVG-Fonts sind entweder abgelöst oder aus dem Browser-Support gefallen, sie können aus dem CSS gestrichen werden.
Bei mehreren Formaten in der src-Liste muss WOFF2 zuerst stehen. Der Browser nutzt das erste Format, das er versteht. Steht WOFF vor WOFF2 (häufige Vorlage aus 2014er Tutorials), lädt der Browser WOFF und ignoriert die effizientere Version. Bei mehreren Schnitten kann das mehrere Hundert KB unnötig kosten.
@font-face {
font-family: "Inter";
src: url("/fonts/Inter.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: optional;
}In den meisten Setups ist nur dieser eine Eintrag pro Schnitt nötig. Browser ohne WOFF2-Support bekommen den Fallback-Stack, der im CSS ohnehin gesetzt sein sollte.
Welche Glyphen lädst du wirklich?
Open Sans Regular liefert rund 900 Glyphen für Latein, Kyrillisch und Griechisch, plus Punctuation, Diakritika und einige Symbole. Eine deutschsprachige Seite nutzt davon vielleicht 250.
Subsetting entfernt aus einer Schrift die Glyphen, die in den Zielsprachen oder im Content nicht vorkommen. Je nach Ausgangsmaterial spart das 30% bis 70% der Datei-Größe, ohne Verlust an Render-Qualität für die Glyphen, die übrig bleiben.
Was DACH wirklich braucht
Für eine deutschsprachige Seite reicht in der Regel:
Basic Latin(U+0000bisU+007F): Buchstaben, Ziffern, ASCII-PunctuationLatin-1 Supplement(U+0080bisU+00FF): deutsche Umlaute, französische Akzente, Euro-ZeichenGeneral Punctuation(U+2000bisU+206F): deutsche Anführungszeichen („“), Geviertstrich, geschütztes Leerzeichen
Google Fonts liefert genau dieses Subset als latin-Variante. Self-Hosting-Tools wie gwfh oder Fontsource bieten es als Standard-Subset.
unicode-range für mehrere Sprachen
Bei mehrsprachigen Shops kann pro Sprache ein eigener @font-face-Block deklariert werden. Der Browser lädt nur das Subset, das im Content tatsächlich auftaucht.
@font-face {
font-family: "Inter";
src: url("/fonts/Inter-Latin.woff2") format("woff2");
unicode-range: U+0000-00FF, /* Basic Latin + Latin-1 (deutsche Umlaute, Akzente) */
U+2000-206F, /* General Punctuation (deutsche „"-Anführungszeichen) */
U+20AC; /* Euro-Zeichen */
}
@font-face {
font-family: "Inter";
src: url("/fonts/Inter-Cyrillic.woff2") format("woff2");
unicode-range: U+0400-04FF; /* Kyrillisch */
}Über-Subsetting bricht User-Generated-Content
Eine Seite mit Basic Latin-only-Subset läuft gut, solange der Content im Subset bleibt. Sobald ein Kunde einen Versand nach „Łódź“ einträgt oder ein Produkttitel aus dem PIM ein türkisches „ş“ enthält, fehlen dem Browser die Glyphen. Die Folge: Im selben Wort taucht der Fallback-Font auf, einzelne Glyphen werden zu leeren Rechtecken (Tofu), oder der Schrift-Mix wird über den Absatz sichtbar.
Pragmatischer Default: Basic Latin und Latin-1 Supplement plus Latin Extended-A (U+0100 bis U+017F) decken Polnisch, Tschechisch, Türkisch und ungewöhnliche Eigennamen mit ab. Der zusätzliche Range kostet nur wenige KB pro Schnitt und verhindert, dass Reviews oder PIM-Importe mit Sonderzeichen den Schrift-Look der Seite brechen.
Tooling
Zwei Subsetting-Strategien, je nach Setup:
- Subset für die Zielsprachen (Empfehlung als Default): einmal pro Build die Sprachen festlegen, die der Shop bedient (Deutsch, Englisch, plus
Latin Extended-Afür Eigennamen). Funktioniert auch bei dynamischem Content aus PIM, Reviews, User-Generated-Content, weil das Subset breit genug bleibt. - Subset für den tatsächlichen Content: Tools wie glyphhanger oder subfont scannen die gerenderten Seiten und nehmen nur Codepoints mit, die wirklich vorkommen. Spart mehr KB, bricht aber, sobald neuer Content Glyphen außerhalb des Subsets enthält.
Die Werkzeuge im Überblick:
- glyphhanger (Node, Wrapper für fonttools): scant URLs und ermittelt tatsächlich gerenderte Codepoints
- subfont (Node, End-to-End): scant HTML, baut Subsets, injiziert
@font-faceund Preload - wawoff2 (npm): reine JS-Konvertierung TTF zu WOFF2 ohne Python-Dependency, aber kein Variable-Font-Subsetting
- hb-subset (HarfBuzz, C-basiert): schneller als pyftsubset und der 2026-Standard für Variable Fonts. Mit
harfbuzzjsals WebAssembly-Bindings auch in JS-Pipelines nutzbar - fonttools / pyftsubset (Python): klassischer Standard mit reichen Optionen, aber Python-Abhängigkeit im Build
In Vite- und Webpack-Builds ist subfont als Plugin integrierbar. Wer Fontsource nutzt, bekommt die Subsets bereits als npm-Package vorbereitet.

Beim Subsetting fallen leicht OpenType-Features mit raus. Default-pyftsubset strippt GSUB/GPOS-Lookups aggressiv, dadurch verschwinden Kerning-Pairs, Ligaturen und Stylistic Sets. Nutzt die Schrift OpenType-Features wie Tabellen-Ziffern für Preise, Ligaturen oder Kapitälchen, sollten diese beim Subsetting explizit erhalten werden: entweder mit --layout-features='*' oder mit einer Liste der benötigten Features (--layout-features=kern,liga,clig,calt,locl,mark,mkmk,ccmp).
Preload: vorsichtig statt automatisch
Ist die Datei klein genug, bleibt die Frage, wann der Browser sie holt.
<link rel="preload" as="font" crossorigin> weist den Browser an, eine Schrift früh zu laden, bevor das CSS sie überhaupt referenziert. Klingt nach einem freien Performance-Gewinn, ist aber ein Trade-off, der selbst Ladezeit kosten kann.
Wann Preload hilft
Das eigentliche Optimierungs-Ziel ist nicht nur ein schneller LCP, sondern eine schnell nutzbare Seite, die den Besucher danach nicht mehr durch sichtbare Schriftwechsel ablenkt. Aus dieser Perspektive sollten die Hauptschriften der Seite immer Preload bekommen (also die ein bis zwei Schnitte, die Above-the-fold gerendert werden, typischerweise Headline und Body-Regular). Preload sorgt dafür, dass die Schrift früh genug da ist, damit der Render entweder direkt mit der Webfont passiert oder der Swap stattfindet, bevor der Nutzer mit dem Lesen beginnt.
Technisch dahinter: Preload startet den Font-Download, sobald der Browser das HTML parst. Ohne Preload entdeckt er den Bedarf erst, wenn er das CSS geparst und das matchende Element gefunden hat. Bei Seiten mit großem CSS-Bundle macht das einen Unterschied von einigen Hundert Millisekunden.
Den gleichen Effekt erreichen HTTP Early Hints (103) mit einem Link: ...; rel=preload-Header. Der Server schickt den Hint los, bevor das HTML fertig gerendert ist. Spart in Setups mit langsamer TTFB nochmal einige Hundert Millisekunden, braucht aber Server-seitigen Support (Nginx ab 1.13.9 mit Modul, Cloudflare als Setting, Vercel/Netlify auf Edge). Dazu mehr in einem eigenen Artikel.
Wann Preload schadet
Erwin Hofman hat in Should you preload fonts for performance? (2025) zwei Mechanismen dokumentiert. Erstens verzögert Preload den ersten Paint, weil der Browser auf den Font wartet: „FCP can be pushed back because the browser waits for the font.“ Zweitens reicht Preload allein oft nicht: „In about 40% page loads, web fonts still miss the first rendering update when fonts were preloaded.“ Wenn die preloadeten Fonts nicht zum LCP-Element gehören, verzögert das den FCP, ohne den eigentlichen Render zu beschleunigen.
Drei Regeln daraus:
- Maximal zwei Fonts preloaden. Mehr stört die Browser-Priorisierung anderer Critical Resources.
- Nur kritische Fonts. Kritisch sind Schriften, die Above-the-fold gerendert werden: Hero-Headline, Body-Copy im sichtbaren Bereich, Navigation. Below-the-fold-Schriften brauchen kein Preload, sie werden ohnehin später beim Scrollen gerendert.
crossoriginist Pflicht. Schriften werden im CORS-Mode geladen, auch wenn sie vom selben Origin kommen. Ohnecrossoriginlädt der Browser die Schrift zweimal: einmal aus dem Preload-Cache, einmal als CORS-Request für die@font-face-Auflösung.
Korrekte Preload-Syntax
<link rel="preload"
href="/fonts/Inter.woff2"
as="font"
type="font/woff2"
crossorigin>Reihenfolge im <head>: Preload vor dem Stylesheet, das das @font-face enthält. Sonst wartet der Browser auf das CSS, bevor er den Preload startet, und der Effekt verpufft.
Vollständige Attribut-Referenz und Browser-Support: MDN: <link rel="preload">.
Anti-Pattern: Preload für alle Fonts
Ein häufiges Anti-Pattern: vier oder fünf <link rel="preload" as="font">-Zeilen für jeden Schnitt einer Familie. Das verschlechtert FCP messbar, weil Chrome den first Paint zurückhält, bis alle preloadeten Fonts geladen sind oder das 1500-Millisekunden-Timeout greift. Jeder zusätzliche Preload verlängert die Wartezeit.
Als pragmatische Faustregel gilt: Preload nur für die ein oder zwei Schnitte, die im Above-the-fold-Bereich tatsächlich gerendert werden. Alle anderen Schnitte werden ohne Preload geladen.
font-display: optional, swap oder fallback
font-display steuert, was der Browser tut, während die Schrift noch lädt. Vier Werte plus den Default auto, jeweils mit eigenem Trade-off zwischen Sichtbarkeit und Layout-Stabilität.
Empfehlung für 90% der Shops: font-display: optional für Body-Text, font-display: swap für Headlines mit Fallback-Metric-Override (siehe nächste Sektion). Wer dieser Default-Konfiguration folgt, hat null CLS durch Schriftwechsel im Body und sichtbare Markenschrift in den Headlines.
Die fünf Werte
| Wert | Block-Period | Swap-Period | Verhalten | Empfohlen für |
|---|---|---|---|---|
auto (Default) | bis zu 3 s | unendlich | wie block in den meisten Browsern | nichts, Default ist die schlechteste Wahl |
block | bis zu 3 s | unendlich | Text unsichtbar bis 3 s, dann Wechsel zur Webfont sobald da | Brand-Fonts mit unbedingtem Wunsch nach erstem Render in der Marke |
swap | 0 ms | unendlich | Fallback sofort sichtbar, Wechsel zur Webfont sobald da | Headlines, Body wenn sichtbarer Wechsel akzeptabel ist |
fallback | 100 ms | 3 s | Fallback sofort, Wechsel nur wenn Webfont in 3 s da, sonst Fallback dauerhaft | Body-Text bei mittelmäßiger Verbindung |
optional | 100 ms | 0 ms | Fallback sofort. Webfont nur sichtbar, wenn in 100 ms geladen, sonst dauerhaft Fallback | Body-Text mit CLS-Priorität |
auto als Default ist in den meisten Browsern eine Variante von block. Eine @font-face-Deklaration ohne expliziten font-display-Wert produziert also bis zu drei Sekunden FOIT, in denen der Text gar nicht sichtbar ist.
Welcher font-display-Wert für welchen Use-Case?
Eine einfache Faustregel für die meisten Setups:
- Body-Text:
font-display: optional. Der Browser zeigt sofort den Fallback. Wenn die Webfont nicht in 100 Millisekunden da ist, bleibt der Fallback dauerhaft.- Vorteil: kein Layout-Shift, kein FOUT, CLS durch den Schriftwechsel bleibt bei null.
- Nachteil: User mit langsamer Verbindung sehen die Marken-Schrift im Body nie. Bei optimierten Self-Hosted Fonts ist die 100-ms-Schwelle für Repeat-Visitors fast immer erfüllt, weil die Schrift aus dem Browser-Cache kommt.
Headlines und Brand-Elemente:
font-display: swap. Die Marken-Wirkung ist hier wichtiger als sofortige Layout-Stabilität. Den Layout-Shift beim Swap eliminierst du mit Fallback-Metric-Overrides.- Caveat: Fallback-Tuning eliminiert den Layout-Shift, nicht den sichtbaren Schriftwechsel selbst. Bei einer Display- oder Editorial-Schrift mit eigenem Charakter (zum Beispiel
Söhne,GT America, eine humanistische Serif) bleibt der Wechsel optisch sichtbar, selbst wennsize-adjustundascent-overrideperfekt sitzen. Wenn der optische Wechsel nicht akzeptabel ist, mussblockverwendet oder die Schrift aggressiv preloaded werden.
- Caveat: Fallback-Tuning eliminiert den Layout-Shift, nicht den sichtbaren Schriftwechsel selbst. Bei einer Display- oder Editorial-Schrift mit eigenem Charakter (zum Beispiel
fallbackist der Kompromiss zwischenswapundoptional. Webfont nur sichtbar, wenn sie in 3 Sekunden da ist, sonst dauerhaft Fallback. In der Praxis selten gewählt.blockist nur zu rechtfertigen, wenn die Brand-Identität so eng an einer spezifischen Schrift hängt, dass ein Aufblitzen des Fallbacks ein Geschäftsproblem wäre. Sehr selten.
Code-Beispiel
/* Body-Text: kein Layout-Shift, dauerhaft Fallback bei langsamer Verbindung */
@font-face {
font-family: "Inter";
src: url("/fonts/Inter.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: optional;
}
/* Headlines: Marke wichtig, Swap akzeptabel */
@font-face {
font-family: "Inter Display";
src: url("/fonts/Inter-Display.woff2") format("woff2");
font-weight: 700;
font-display: swap;
}Was ist FOIT, was ist FOUT, und welcher Effekt ist schlimmer?
FOIT (Flash of Invisible Text) bedeutet: Der Browser zeigt gar keinen Text, bis die Webfont geladen ist. FOUT (Flash of Unstyled Text) bedeutet: Der Browser zeigt sofort den Fallback und wechselt später zur Webfont, mit sichtbarem Schriftwechsel im laufenden Render.
FOIT ist in den meisten Fällen schlimmer. Während FOIT läuft, ist der Text weg. Nutzer können nicht lesen, nicht klicken, nicht entscheiden. Bei langsamer Verbindung dauert das Sekunden. FOUT ist störend, aber der Inhalt ist sofort lesbar.
Die Wahl steckt in font-display: block produziert FOIT, swap produziert FOUT, optional vermeidet beide (Webfont kommt nur, wenn sie schnell genug ist, sonst dauerhaft Fallback).
Wie verhinderst du Layout-Sprünge?

Eine Webfont und ihr Fallback haben unterschiedliche Metriken: andere Zeichenbreite, andere x-Höhe, andere Versalhöhe. Wenn der Browser von Fallback auf Webfont wechselt (font-display: swap), rechnet er das Layout neu durch. Die Konsequenz: Zeilenumbrüche verschieben sich, Buttons rutschen nach unten, Bilder springen.
CLS misst diesen Layout-Shift. Zielwert: unter 0,1. Bei Schriftwechsel auf Body-Text liegt der CLS-Effekt oft zwischen 0,05 und 0,2. Ein einzelner Webfont-Wechsel kann den Wert allein über das Limit treiben.
Fallback-Metric-Overrides
ascent-override, descent-override und line-gap-override sind seit Chrome 87 (November 2020) und Firefox 89 (Juni 2021) verfügbar. Die size-adjust-Property kam später, mit Chrome 92 (Juli 2021) und Firefox 92 (September 2021). Vier CSS-Properties auf einer separaten @font-face-Deklaration:
size-adjust: skaliert die Glyph-Größe relativ zur deklarierten Pixel-Größeascent-override: überschreibt die Aufstrich-Höhe (Oberlängen)descent-override: überschreibt die Abstrich-Höhe (Unterlängen)line-gap-override: überschreibt den Zeilenabstand
Die konkreten Werte hängen von der Webfont und dem Fallback ab. Manuelles Ausprobieren ist mühsam, deshalb gleich zum richtigen Tool greifen: das Build-Tool fontaine berechnet die Override-Werte automatisch. Das folgende Beispiel zeigt typische Werte für Inter mit Arial als Fallback:
@font-face {
font-family: "Inter Fallback";
src: local("Arial"), local("Liberation Sans"), local("Helvetica");
ascent-override: 90%;
descent-override: 22.4%;
line-gap-override: 0%;
size-adjust: 107%;
}
body {
font-family: "Inter", "Inter Fallback", sans-serif;
}Mehrere local()-Optionen sind nötig, weil Arial nicht überall vorhanden ist: auf Linux wird Liberation Sans als Default-Sans gemappt, das hat fast identische Metriken zu Arial. Helvetica deckt ältere macOS-Versionen ab. Damit greifen die Override-Werte auf allen drei Plattformen ähnlich gut.
Der Browser nutzt den Fallback mit angepassten Metriken, bis die Webfont da ist. Beim Swap bleibt das Layout praktisch identisch, weil Zeichenbreite und Höhe schon zusammenpassen. CLS durch Schriftwechsel: null.
Tools für die Override-Werte
Drei Tools übernehmen die Berechnung:
- fontaine (Node, npm): Anthony Fus Library scannt deine Webfont, berechnet Override-Werte für gängige Fallbacks (
Arial,Times) und generiert die@font-face-Blöcke automatisch. Build-Step-tauglich. - font-style-matcher (Web-UI): Visueller Vergleich zweier Schriften, Werte werden live angepasst und als CSS ausgegeben. Gut für einmaliges Tuning.
@nuxt/fontsundnext/fontintegrieren fontaine intern. Wer auf einem dieser Frameworks aufbaut, bekommt die Overrides ohne Zusatz-Setup beim Build.

Reicht font-display: swap oder brauche ich optional?
Beides ist legitim, mit unterschiedlichen Trade-offs. swap zeigt die Webfont sofort, sobald sie da ist. Wenn du die Fallback-Metriken mit size-adjust und ascent-override getuned hast, ist der CLS beim Swap praktisch null und der Schriftwechsel kaum sichtbar. optional zeigt die Webfont nur, wenn sie in 100 Millisekunden geladen ist. Bei langsamer Verbindung bleibt der Fallback dauerhaft, ohne jeden Wechsel.
Die Wahl hängt davon ab, wie wichtig die Marken-Schrift im Body ist. Bei Brand-Schriften für Headlines: swap plus Fallback-Tuning. Bei Body-Text in Sans-Serif ist optional die ruhigere Wahl, weil sie auf jeder Verbindung CLS=0 liefert.
Icon-Fonts oder SVG: was ist besser?
Bisher ging es um Text-Schriften. Icons haben eigene Performance-Probleme und eine deutlich einfachere Lösung.
Drei Probleme von Icon-Fonts
Font Awesome, Material Icons als Webfont, Glyphicons. Alle drei haben dieselben Standard-Probleme:
- Accessibility. Tyler Sticka hat das Kernproblem in Seriously, Don’t Use Icon Fonts (Cloud Four, 2015) auf den Punkt gebracht: „Most assistive devices will read aloud text inserted via CSS, and many of the Unicode characters icon fonts depend on are no exception.“ Konkret: Screenreader sprechen Unicode-Codepoints aus („schwarzer Stern“), wenn das Icon nicht explizit per
aria-hiddenversteckt wird. Custom-Stylesheets von Sehbehinderten (zum Beispiel OpenDyslexic) ersetzen die Webfont, das Icon-Glyph wird zur Tofu-Box. Michael Irigoyen hat die Argumente 2021 mit aktuellen Daten bestätigt. - Layout. Glyphen kämpfen mit
line-height,vertical-alignund Baseline. SVG mitwidth: 1em; height: 1emskaliert vorhersehbar mit derfont-size, ohne Baseline-Probleme. - Mehrfarbig. Icon-Fonts können nur eine Farbe pro Glyph (Color Fonts mit
COLR-Tabelle existieren, sind in der Praxis aber selten unterstützt). SVG kann pro Path eine eigene Farbe haben, mit CSS-Variablen sogar dynamisch.
Selbst Font Awesome empfiehlt für moderne Frameworks die SVG-Variante.
SVG-Sprite als Alternative
Empfohlene Variante: ein gemeinsames SVG-Sprite-File für alle Icons, vom eigenen Origin ausgeliefert mit langem Browser-Cache. Genau ein HTTP-Request für die ganze Site, danach gecacht.
<!-- /icons/sprite.svg (einmalig auf dem Server) -->
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-cart" viewBox="0 0 24 24">
<path d="..." fill="currentColor"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<path d="..." fill="currentColor"/>
</symbol>
</svg>
<!-- Verwendung im HTML -->
<button>
<svg width="1em" height="1em" aria-hidden="true">
<use href="/icons/sprite.svg#icon-cart"/>
</svg>
Warenkorb
</button>fill="currentColor" übernimmt die color-CSS-Property des umgebenden Elements. Genau das Verhalten von Icon-Fonts, ohne deren Nachteile. width: 1em; height: 1em skaliert mit font-size. Browser-Support für currentColor ist universal seit etwa 2011 (mit IE 9).
Caveats für externe Sprites: Cross-Origin-Sprites werden ohne korrekte CORS-Header nicht geladen. Liefere das Sprite deshalb vom selben Origin aus wie die Seite. Firefox behandelt externe SVG-Sprites als eigenständiges Dokument im Kontext der CSP (Content Security Policy): Nicht img-src greift, sondern default-src muss das Sprite erlauben.
Inline-Sprite (alle <symbol>-Definitionen direkt im HTML, keine externe Datei) ist nur dann sinnvoll, wenn keine Asset-Pipeline existiert oder wenn die Seite nur ein einziges Icon nutzt. Sonst bläht es jede HTML-Antwort auf und nutzt kein Caching.
npm-Pakete als Icon-Quelle
- Lucide (1.500+ Icons, ISC): Standard-Default, framework-agnostisch, gutes Tree-Shaking
- Heroicons (292 Icons, MIT): vom Tailwind-Team, kuratiert
- Phosphor (9.000+ Icons in 6 Gewichten, MIT): wenn Gewichts-Variation gebraucht wird
- Tabler Icons (5.900+ Icons, MIT): breit, gut für Dashboards
- Bootstrap Icons (2.000+, MIT): für Bootstrap-UIs
Wie integrierst du Webfonts in den Build?
Damit ist das Verhalten geklärt. Bleibt die Frage, wie das Setup aussieht, das diese Optionen zuverlässig liefert.
Schriften gehören in die Asset-Pipeline, nicht in das /public-Verzeichnis. Diese Regel löst die meisten Cache- und Versionierungs-Probleme automatisch.
Warum gehören Fonts in die Asset-Pipeline?
Der Standard-Build-Prozess (Vite, Webpack, esbuild, Rollup) hängt einen Content-Hash an jeden Asset-Filename: Inter.a3b9f.woff2 statt Inter.woff2. Damit lassen sich folgende Cache-Header sicher setzen:
Cache-Control: public, max-age=31536000, immutableEin Jahr Browser-Cache, ohne Revalidierung. Ein Jahr (31.536.000 Sekunden) ist die etablierte Konvention im Web. Die HTTP-Spec (RFC 9111) erlaubt formal deutlich höhere Werte (bis 2^31 Sekunden, rund 68 Jahre), aber Werte über ein Jahr bringen praktisch keinen Mehrwert. immutable ist der eigentliche Hebel: das Attribut sagt dem Browser, dass sich die Datei unter dieser URL nie ändert, also keine Revalidierung mehr nötig ist. Bei einem Update der Schrift ändert sich der Content-Hash im Filename, der Browser lädt automatisch die neue Datei.
Wer Schriften in /public ablegt, hat keinen Hash. Folge: entweder aggressives Caching mit Cache-Bust-Problemen oder vorsichtiges Caching mit unnötigen Revalidierungen.
Mini-Workflow für ein Vanilla-Setup
Wer kein Framework nutzt und alles selbst zusammenbaut, kommt mit fünf Schritten aus:
- Variable Font installieren. Beispiel mit Inter:
npm install @fontsource-variable/inter. Die WOFF2-Dateien liegen danach unternode_modules/@fontsource-variable/inter/files/. Per Build-Step oder manuell nachpublic/fonts/kopieren, damit der Pfad in Step 3 stimmt. - WOFF2-Subset bauen (falls nicht schon vorhanden). Der robusteste Default ist ein Subset auf die Zielsprachen plus eine Allow-List für seltene, aber kalkulierbare Glyphen. Für eine deutschsprachige Seite mit gelegentlichen Eigennamen aus Polen, Tschechien oder der Türkei sind das
Basic Latin(U+0000-007F) plusLatin-1 Supplement(U+0080-00FF) plusLatin Extended-A(U+0100-017F) plusGeneral Punctuation(U+2000-206F). Mitpyftsubset:
pyftsubset Inter.ttf \
--output-file=Inter-subset.woff2 \
--flavor=woff2 \
--unicodes="U+0020-007F,U+00A0-00FF,U+0100-017F,U+2000-206F,U+20AC" \
--layout-features='*'Optional als Ergänzung: Tools wie subfont oder glyphhanger scannen das gerenderte HTML und ermitteln die tatsächlich vorkommenden Codepoints. Das ist nützlich, um den Subset gegenzuprüfen oder bei rein statischen Sites mit klar abgegrenztem Content noch ein paar KB einzusparen. Als Hauptstrategie ist es zu fragil: sobald Reviews, PIM-Importe oder neue Produkte Sonderzeichen einbringen, fehlen dem Browser die Glyphen.
Wer das Scanning trotzdem nutzt, sollte es gegen die gebaute HTML laufen lassen (dist/index.html oder build/index.html), nicht gegen die Source. Sonst sieht der Scanner bei Single-Page-Apps nur das App-Shell und der Subset wird unbrauchbar klein. Bei mehrsprachigen Sites mit User-Generated-Content sollte das Scanning über den breitesten Content-Pool laufen, der erreichbar ist.
- Critical CSS inline ins HTML schreiben, mit
@font-face-Block und Fallback-Override. Im Beispiel unten signalisierttech("variations")dem Browser, dass die Datei eine Variable Font ist. Browser ohne Variable-Font-Support (sehr selten) ignorieren densrc-Eintrag und fallen auf den nächsten zurück. Bei statischen Schnitten kann dertech()-Hinweis weggelassen werden. Derfont-weight: 100 900-Bereich definiert, welche Gewichte aus der Achse interpoliert werden dürfen, ohne den Block zu duplizieren.
<style>
@font-face {
font-family: "Inter";
src: url("/fonts/Inter-Variable.woff2") format("woff2") tech("variations");
font-weight: 100 900;
font-style: normal;
font-display: optional;
}
@font-face {
font-family: "Inter Fallback";
src: local("Arial"), local("Liberation Sans"), local("Helvetica");
ascent-override: 90%;
descent-override: 22.4%;
line-gap-override: 0%;
size-adjust: 107%;
}
body { font-family: "Inter", "Inter Fallback", sans-serif; }
</style>Die ascent-override/descent-override/size-adjust-Werte oben sind Inter-zu-Arial-spezifisch. Für andere Schrift-Paare berechnest du sie mit Fontaine oder dem Capsize-Calculator. Falsche Werte erzeugen sichtbares CLS, genau den Effekt, den der Override eigentlich verhindern soll.
- Optional: Preload für die LCP-Schrift, wenn das LCP-Element davon abhängt:
<link rel="preload" href="/fonts/Inter-Variable.woff2" as="font" type="font/woff2" crossorigin>- Cache-Header auf dem Server setzen. Apache:
AddType font/woff2 .woff2
<FilesMatch "\.woff2$">
Header set Cache-Control "public, max-age=31536000, immutable"
Header set Access-Control-Allow-Origin "*"
</FilesMatch>Nginx:
types {
font/woff2 woff2;
}
location ~* \.woff2$ {
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Access-Control-Allow-Origin "*";
}AddType (Apache) bzw. types-Block (Nginx) setzt den korrekten MIME-Typ; ohne das liefert Apache TTF/WOFF2 oft als application/octet-stream und strenge CORS-Browser meckern. Access-Control-Allow-Origin: * ist für Schriften unkritisch, weil sie in keinem Cookie- oder Session-Kontext stehen. Falls die Fonts auf einer Subdomain liegen (cdn.shop.de) und vom Hauptdomain (shop.de) geladen werden, ist der Header zwingend.
Verifikation: Im Browser DevTools-Network-Tab die Schrift-Antwort öffnen, Cache-Control-Header prüfen.
Inline-Critical-CSS für @font-face
Den @font-face-Block direkt ins HTML zu schreiben (statt aus einer extern geladenen Stylesheet-Datei) bringt einen subtilen Performance-Vorteil. Der Browser lädt nur Schriften, von denen er weiß, dass er sie braucht. Diese Relevanz kann er erst durch das @font-face plus eine font-family-Referenz auf einem Element ermitteln. Liegt das CSS in einer externen Datei, muss der Browser zuerst diese Datei laden, parsen und matchen, bevor er den Schrift-Download startet. Bei einem Inline-Block im <head> startet die Schrift-Discovery sofort beim ersten HTML-Parse.
Wichtig: nur das Critical CSS inline schreiben (@font-face-Blocks plus die font-family-Deklaration für body und Headlines). Das gesamte Stylesheet inline zu platzieren frisst den Vorteil wieder auf.
Framework-Defaults statt Eigenbau
In modernen Frameworks ist der Workflow oben weitgehend automatisiert. Defaults nutzen, nicht selbst basteln. Manuelle @font-face-Blöcke im Theme verlieren die automatische Hash-Vergabe und die Fallback-Overrides.
- Next.js:
next/font/local,next/font/google→ Docs - Nuxt 3+:
@nuxt/fonts→ Docs. Glyph-Subsetting nicht enthalten, separat über Fontsource-Pakete. - Astro 6+:
fonts-Config (stable seit März 2026) → Docs - Vite (ohne Meta-Framework):
unplugin-fontsplus@fontsource/*plusfontaine - SvelteKit, Remix / React Router 7, Solid Start: kein Built-in, Plain-Vite-Stack manuell. Walkthroughs: Remix/RR7, SvelteKit plus Fallback-Metrics
Reproduzierbarer Build
Subsetting darf nicht im Theme-Repo als gepatchte Datei liegen. Wenn später ein Glyph dazukommt (neue Sprache, neues Symbol im Content), muss der Subset einfach neu gebaut werden können. Konkret:
- Subsetting-Befehl im
package.json-Script oder im CI-Pipeline-Step - Eingangs-TTF-Datei und Subset-Range im Repo versioniert
- Output-WOFF2 als Build-Artefakt, nicht als manuell gepflegte Datei
Ohne reproduzierbaren Build wird bei der nächsten Anpassung eine Glyphe vergessen. Das Ergebnis ist ein Fehler, der für Entwickler schwer zu finden ist, von Nutzern aber definitiv bemerkt wird: einzelne Buchstaben in einer anderen Schrift mitten im Text.
Plattform-Besonderheiten
In Shopify, WordPress, Shopware oder Magento ist der Workflow anders, weil Theme-Editoren und Plugins eigene Annahmen haben. Die Logik bleibt identisch, die Hebel-Punkte unterscheiden sich. Wenn du Unterstützung mit deiner spezifischen Plattform brauchst, meld dich gerne.
So prüfst du, ob es wirklich besser geworden ist
Jede Optimierung braucht eine Messung davor und eine Messung danach. Ohne den Vergleich bleibt unklar, ob die Änderung wirklich gewirkt hat oder nur etwas anderes auf der Seite passiert ist.
Verifikations-Checkliste
Drei Runs Lighthouse Mobile vor der Änderung, drei Runs danach. Median nehmen, dann diese Werte vergleichen:
- LCP (Largest Contentful Paint): sollte gesunken sein, wenn das LCP-Element ein Text-Element ist (Headline, Hero-Subline, Produkt-Titel)
- CLS (Cumulative Layout Shift): sollte gesunken sein bei
font-display: swapmit Fallback-Tuning oder Wechsel aufoptional - Network-Tab im Chrome DevTools mit Filter
font: weniger Requests, kleinere Größen pro Request, kein zusätzlicher Origin (fonts.gstatic.comist weg, wenn Self-Hosting umgesetzt wurde) - Render-Blocking: Lighthouse-Audit „Ensure text remains visible during webfont load“ sollte keine Warnung mehr werfen
Wenn die Veränderung kleiner ist als die Run-zu-Run-Streuung (~50 ms LCP), ist sie nicht messbar wirksam. Dann tiefer ins Trace im Performance-Panel schauen oder Real-User-Daten via CrUX-Report ziehen.
Drei Fragen für dein Tech-Team oder deine Agentur
Wenn die Umsetzung in deinem Team oder bei deiner Agentur liegt, sind das die drei Fragen, mit denen du in das Gespräch gehst:
1. Werden unsere Schriften vom eigenen Server ausgeliefert oder von fonts.gstatic.com?
Wenn extern: bitte self-hosten. Performance- und DSGVO-Vorteil in einem.
2. Wie viele Schriftgewichte laden wir wirklich, und wie viele sind durch CSS auch genutzt?
Mehr als drei genutzte Gewichte ist meistens Page-Builder-Default, nicht Notwendigkeit.
3. Welches Schrift-Format liefern wir aus, und steht font-display auf jedem @font-face?
TTF/OTF im Web-Output ist 2026 ein Quick-Win für WOFF2-Konvertierung. Fehlendes font-display produziert FOIT auf jeder Verbindung.
Diese drei Fragen decken die größten Anti-Patterns ab. Eine Antwort wie „kommt automatisch über das Theme“ ist kein Argument, sondern ein Ausgangspunkt für die Audit-Diskussion.
Häufige Fragen
Sind Google Fonts DSGVO-konform?
Wenn sie über die Google-Server (fonts.googleapis.com, fonts.gstatic.com) eingebunden werden: nein. Das LG München I hat am 20. Januar 2022 (Az. 3 O 17493/20) entschieden, dass die dynamische Einbindung ohne Einwilligung gegen die DSGVO verstößt. Self-Hosting löst das Problem rechtlich und Performance-mäßig in einem Schritt.
Sind Webfonts ein Google-Ranking-Faktor?
Direkt: nein. Indirekt: ja, über Core Web Vitals. Schlecht geladene Schriften treiben LCP und CLS nach oben, beide sind weiche Ranking-Signale. Eine optimierte Schrift-Konfiguration verbessert nicht das Ranking selbst, sie nimmt dem Ranking eine Bremse weg.
Welcher font-display-Wert ist der beste für PageSpeed?
Body-Text: font-display: optional. Headlines mit Brand-Schrift: font-display: swap plus Fallback-Metric-Override. block und auto produzieren FOIT und sollten vermieden werden.
Wie viele Fonts darf ich preloaden?
Maximal zwei. Mehr Preloads stören die Browser-Priorisierung anderer Critical Resources und verzögern den ersten Paint. Wenn du mehr als zwei Schriften für Above-the-fold brauchst, ist das eher ein Hinweis darauf, dass die Schrift-Auswahl reduziert werden sollte.
Wie viele Schriftgewichte sind zu viele?
Regular und Bold decken 80% der Anwendungsfälle. Ein drittes Gewicht für Display ist legitim, oft Medium oder SemiBold für Headlines. Mehr als drei Gewichte ist meistens Page-Builder-Default, der ungeprüft übernommen wurde. Fünf oder sieben Gewichte im Theme zu finden ist Standard, in der Praxis genutzt werden zwei oder drei.
Wie ersetze ich Font Awesome ohne Performance-Verlust?
Inline-SVG-Icons oder ein SVG-Sprite sind kleiner als eine Icon-Font, lassen sich mit currentColor über die color-Property färben und mit width: 1em; height: 1em an die font-size koppeln. Konkrete npm-Pakete als Quelle: Lucide, Heroicons, Phosphor, Tabler Icons.
Funktioniert Font-Optimierung auch in Shopify, WordPress oder Shopware?
Ja, die Mechaniken sind plattformunabhängig: WOFF2-Format, Subsetting, font-display, Preload und Cache-Header gelten überall. Die Hebel-Punkte unterscheiden sich (Theme-Editor, Plugin-System, Liquid- vs. Twig-Templates). Wenn du Unterstützung mit deiner spezifischen Plattform brauchst, meld dich gerne.
Stand: Mai 2026
Hohe Ladezeiten durch Webfonts?
Mein Thema.
Ich unterstütze E-Commerce-Teams dabei, ihre Core Web Vitals in den grünen Bereich zu bringen. Durch Messungen finde ich die größten Bremsen deines Shops und löse sie wahlweise für dich oder mit deinem Team.
Egal ob Shopify, WordPress, Shopware oder gewachsenes Legacy-Projekt.

Fullstack Performance Tuner
