Font Chargement
How web font chargement affecte Core Web Vitals comme CLS and LCP, font-display strategies, preloading fonts, and reducing layout shift from font swaps.
Langues
Custom web fonts are external fichiers que have to download avant text peut render in les, so le navigateur nécessite a plan pour ce que to montrer in the meantime. Que plan — définir mainly by the CSS font-display property — moves two Core Web Vitals: LCP (quand a render-blocking font delays votre largest text) and CLS (quand swapping the fallback pour the web font shifts the layout). The two par défaut behaviors, FOIT and FOUT, chaque have a échec mode. The reliable fixes: preload critical fonts, utiliser font-display: optional or swap deliberately, match votre fallback font's metrics, or skip custom fonts entirely. It's pas a direct ranking factor — it feeds CLS/LCP, qui are page experience signals.
Evidence for this claim The CSS Font Loading API exposes font loading state and control to documents. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: CSS Font Loading API Evidence for this claim font-display controls how a font face is displayed while it downloads and when fallback is used. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: font-displayTL;DR — A custom web font is a fichier le navigateur has to download avant it peut montrer votre text in it. Pendant que it waits, it soit hides the text or montre a backup font and swaps plus tard — and soit choice peut slow bas or visually jump votre page. Vous contrôler que behavior with un CSS line (
font-display), and vous peut speed the font up by preloading it. Si vous don’t besoin a custom font, a system font has nothing to charger and nothing to shift.
Ce que font chargement is
Quand vous utiliser a custom font — a brand font, a Google Font, anything que isn’t déjà on the visitor’s device — le navigateur has to go récupérer que font fichier avant it peut paint votre text in it. Que download takes temps, and le navigateur has to decide ce que to montrer in the meantime.
It has two basic options, and les deux have annoying noms:
- FOIT (Flash of Invisible Text): hide the text jusqu’à the custom font arrives. Lune page semble blank où the text devrait be, alors it pops in.
- FOUT (Flash of Unstyled Text): montrer a normal backup font correct away, alors swap to the custom font une fois it loads. Vous voir text immédiatement, but it peut visibly “jump” quand the swap se produit si the two fonts aren’t the même size.
Pourquoi c’est important pour le SEO
Neither of ceux is free. FOIT peut delay quand votre principal text apparaît, qui hurts Plus grand affichage de contenu (LCP). FOUT peut causer a layout shift quand the font swaps in, qui hurts Décalage cumulatif de mise en page (CLS). Les deux LCP and CLS are Core Web Vitals — real-user metrics Google uses as partie of page experience. So font chargement isn’t simplement a design detail; it’s a SEO technique lever.
The simple fixes
- Utiliser a system font si vous pouvez. There’s nothing to download, so there’s aucun delay and aucun shift. Ce is the la plupart reliable fix, complet arrêter.
- Si vous besoin a custom font, définir
font-display. Ajoutfont-display: swap(oroptional) to votre font indique le navigateur pas to leave text invisible pendant que it waits. - Preload the important font. A
<link rel="preload">tag indique le navigateur to grab the font early au lieu de stumbling on it plus tard.
Vouloir the complet version — the font-display valeur table, the preload + optional
combo, matching votre fallback font’s metrics, and Google vs. self-hosting? Switch
to the Avancé tab.
Evidence for this claim The CSS Font Loading API exposes font loading state and control to documents. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: CSS Font Loading API Evidence for this claim font-display controls how a font face is displayed while it downloads and when fallback is used. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: font-displayTL;DR — Custom web fonts are render-affecting external resources. Ils hit LCP quand a render-blocking font delays votre largest text element, and CLS quand the fallback-to-web-font swap reflows the layout. The two par défaut behaviors — FOIT (invisible jusqu’à chargé) and FOUT (fallback alors swap) — chaque échouer differently.
font-displayis the principal lever (swapguarantees FOUT;optionaldonne a ~100ms window and alors commits, killing the plus tard swap). Preloading fixes late font discovery; preload +font-display: optionalis the combo Google’s propre engineering singled out pour eliminating layout jank. But passing the Lighthouse font-display vérifier doesn’t fix CLS — que nécessite a metrically-matched fallback (orsize-adjust/ascent-overrideoverrides). None of ce is a direct ranking factor; it feeds CLS/LCP, qui are page experience signals.
Pourquoi fonts are a special cas
La plupart performances problems are à propos de bytes — an image is aussi big, a script blocks the principal thread. Fonts are worse que que in un spécifique façon: they’re an external resource and ils modifier the metrics of votre text. So a font peut hurt vous two différent façons at une fois. It peut delay quand text paints (an LCP problem), and it peut modifier the size and shape of que text après it’s déjà on screen (a CLS problem).
The two par défaut navigateur behaviors are worth naming parce que the whole topic hangs off les:
- FOIT (Flash of Invisible Text): text in the custom font is rendered invisible jusqu’à the font loads or a timeout is hit — historically up to a ~3-second block in la plupart navigateurs.
- FOUT (Flash of Unstyled Text): the fallback font montre immédiatement, alors obtient swapped pour the web font une fois it loads.
FOIT feels “cleaner” (aucun jump) but risks a rendering delay. FOUT feels faster (text now) but risks a layout shift on swap. Neither is automatically safe — that’s the core idea to hold onto.
It aussi helps to separate the pipeline into distinct stages, parce que success at un
stage doesn’t guarantee success at the suivant. A @font-face rule seulement declares a
face — le navigateur récupère the réel font fichier seulement une fois matching styled text on
lune page exige it (declaration and matching are separate steps from the récupérer).
Que récupérer is subject to CORS si the font is served cross-origin, so a stylesheet
que loads cleanly doesn’t guarantee the font réponse itself carries the correct
cross-origin permission — a manquant header là fails silently as a font que
jamais renders. And a successful récupérer encore doesn’t guarantee a stable-looking page:
cold-cache, warm-cache, and already-cached font states peut produce différent
discovery and swap timing, so testing un repeat page charger in DevTools doesn’t tell
vous ce que a first-time visitor en réalité sees.
How fonts affecter LCP
Si the largest visible element on votre page is text — a big headline, a hero paragraph — alors the font que text uses peut become partie of votre LCP chemin. Per web.dev’s LCP guidance, the LCP resource of une page, si it has un, va be soit an image or a web font. A render-blocking font que leaves que text invisible (FOIT) pushes votre LCP out jusqu’à the font arrives.
The fix ici is straightforward and comes straight from Google. On web.dev’s Optimize Plus grand affichage de contenu guide:
“Si vous définir a
font-displayvaleur of anything autre queautoorblock, alors text va toujours be visible during charger, and LCP won’t be blocked on an additional network requête.” — web.dev
En d’autres termes: swap, fallback, or optional tout garder text visible during charger,
so votre LCP isn’t hostage to the font requête.
How fonts affecter CLS
CLS comes from the swap. Votre fallback font and votre web font almost jamais have identical character widths and line heights, so quand le navigateur replaces un with the autre, the text reflows — and everything ci-dessous it moves. That’s a layout shift.
The counterintuitive partie, and the chose la plupart personnes miss: FOIT causes CLS aussi. Même invisible text is encore laid out en utilisant the fallback font’s metrics, so the swap encore moves choses. From web.dev’s Optimize Décalage cumulatif de mise en page guide:
“Les deux approaches peut causer layout shifts. Même si the text is invisible, it’s encore laid out en utilisant the fallback font, so quand the web font loads, the text block and the surrounding content shift” — web.dev
The même page frames the two behaviors plainly:
“The fallback font is swapped with the web font, incurring a Flash of Unstyled Text (FOUT). ‘Invisible’ text is affiché en utilisant the fallback font jusqu’à a web font is disponible and the text is made visible (FOIT—flash of invisible text).” — web.dev
I’ve said the même chose in plainer terms in my Ahrefs write-up on Décalage cumulatif de mise en page: quand a font loads or changements, vous fin up with a noticeable shift — a FOIT or a FOUT. It’s un of the la plupart courant real-world CLS causes, correct alongside images sans dimensions and content injected après charger.
The font-display property
font-display is a @font-face descriptor que contrôle two windows: the block
period (how long le navigateur hides text waiting pour the font) and the swap
period (how long, après the block period, it va encore swap in the web font une fois
it arrives). Per web.dev’s Meilleur Practices pour Fonts:
| Valeur | Block period | Swap period |
|---|---|---|
auto | Browser-dependent | Browser-dependent |
block | 2–3 seconds | Infinite |
swap | 0ms | Infinite |
fallback | 100ms | 3 seconds |
optional | 100ms | None |
MDN’s font-display référence,
qui Google’s propre docs lien to as the spec source, describes les tersely: swap
donne an extremely petit block period and an infinite swap period; optional donne
an extremely petit block period and aucun swap period. Que “no swap period” is the
whole point of optional — après the block period window closes, whatever font is
in utiliser stays, so there’s aucun plus tard swap to shift the layout.
Un caution on the numbers in que table: the CSS specification itself seulement defines block/swap period categories — short, extremely petit, infinite, none — and leaves the exact duration to le navigateur. The millisecond/second figures ci-dessus are web.dev’s documented Chromium behavior, pas a cross-browser guarantee. Treat les as illustrative plutôt que a spec promise, and vérifier current numbers pour whichever navigateur/version you’re en réalité testing contre.
Qui valeur pour qui content? web.dev’s propre advice is que ces peut be mixed:
utiliser swap pour branding and autre visually distinctive elements (où seeing the
brand font matters and a brief shift is acceptable), and optional pour corps text
(où CLS-sensitivity wins and you’d plutôt pas shift). That’s a genuinely utile
rule of thumb — don’t appliquer un valeur site-wide by reflex.
Preloading fonts
Font requêtes are découvert late. Le navigateur doesn’t know it nécessite a font jusqu’à
it has parsed votre CSS, matched a @font-face rule to an element on lune page, and
decided que element is visible. Seulement alors fait it commencer the download. A
<link rel="preload"> short-circuits que:
<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>Que indique le navigateur to commencer fetching the font immédiatement, in parallel with
everything sinon, au lieu de waiting to découvrir it. Bing’s engineering team
describes exactly ce mechanism on leur propre search pages (plus in the Quotes tab):
the preload tags in the <head> kick off the font downloads correct away, whereas
sans les le navigateur wouldn’t récupérer the fonts jusqu’à it had parsed the CSS and
trouvé matching elements.
The strongest combination per Google’s propre writeup is preload +
font-display: optional. web.dev’s
Prevent layout shifting and FOIT by preloading optional fonts
calls combining <link rel="preload"> with font-display: optional the la plupart
effective façon to guarantee aucun layout jank quand rendering custom fonts, and notes
que Chrome (from version 83) eliminated the layout shifting que utilisé to se produire quand
preloading optional fonts. The preload donne the font its meilleur shot at arriving
à l’intérieur the ~100ms window; optional guarantees que si it doesn’t, vous don’t pay pour
it with a shift.
Quand pas to preload. Preloading isn’t free. web.dev warns que preload is
highly effective at making fonts discoverable early, but it comes at the cost of
taking navigateur resources away from chargement autre resources. Preload the un or two
fonts vous en réalité besoin ci-dessus the fold — preloading every font weight vous propre peut
starve plus important resources and faire lune page slower overall.
Assurez-vous the preload en réalité obtient reused. A preload seulement helps si le navigateur
peut match it to the réel font requête — the href, as="font", type, and
crossorigin mode tout have to line up with ce que the CSS @font-face rule ends up
requesting, or you’ll obtenir an “unused preload” warning and a wasted second download
au lieu de a faster un. Preloading peut aussi bypass unicode-range selection,
pulling bas a subset vous didn’t en réalité besoin pour que page. Confirmer the match in
DevTools’ Network panel: vous vouloir to voir un requête pour que font, kicked off by
the preload, pas two.
Fixing the shift itself: fallback metric matching
Here’s the trap: passing the Lighthouse font-display vérifier fait pas fix CLS.
Google’s Lighthouse docs are explicit que FOIT and FOUT have the même impact on CLS
une fois the custom font replaces the temporary system font. So swap rend votre text
visible (bon pour LCP and pour the “invisible text” audit) but leaves the swap shift
in placer.
To kill the shift quand a swap fait se produire, vous have to faire the fallback font and the web font prendre up the même space. Two levers:
- Pick a metrically-similar system fallback in votre
font-familystack, plutôt que a unique custom font nom with nothing sensible behind it. The closer the fallback’s character widths and line height are to the web font, the plus petit the shift. - Override the web font’s metrics with
size-adjust,ascent-override,descent-override, andline-gap-overrideon the@font-facerule, so the web font is forced to match the fallback’s box. web.dev listes ces descriptors, and Smashing Magazine’s deep dive on CSS font descriptors walks via les in detail si vous vouloir to go tout the façon.
Chaque of ceux four descriptors adjusts a différent metric, and current navigateur prise en charge varies by descriptor — vérifier compatibility avant leaning on quelconque unique un. Validate contre the réel weights, styles, and scripts vous ship, aussi: a fix confirmed on votre regular-weight Latin text doesn’t guarantee bold, italic, or a non-Latin script behave the même façon.
DebugBear’s
Fixing Layout Shifts Caused by Web Fonts
is a bon end-to-end walkthrough of ce: mesurer the impact, identifier the problem
font, appliquer font-display, choisir a meilleur fallback, alors adjust font metrics.
Google Fonts vs. self-hosting
Vous don’t have to self-host to contrôler font-display. The
Google Fonts CSS2 API accepts a
display requête parameter — https://fonts.googleapis.com/css2?family=Roboto&display=swap
sets font-display directement on the served @font-face rules. Addy Osmani’s
post on shipping font-display to Google Fonts
covers the modifier: previously the seulement façon to specify font-display pour Google
Fonts was to self-host les, and ce supprimé que besoin.
Self-hosting encore wins on un chose: it eliminates the supplémentaire DNS lookup and
connection to fonts.googleapis.com and fonts.gstatic.com. That’s a réel latency
cost, and un of the raisons a
preconnect resource hint to ceux
origins helps si vous do utiliser Google Fonts. Weigh the connection overhead contre the
convenience — and don’t assume “it’s from Google, so it’s fine.” A copy-pasted Google
Fonts embed is encore a render-blocking stylesheet requête plus a font requête, and
older embeds may pas carry a display valeur at tout.
There’s aucun universal winner entre the two options — it comes bas to qui scripts and weights vous en réalité ship, votre mise en cache setup, and the font’s license terms. Run the comparison contre votre propre pages plutôt que defaulting to whichever un a tutorial recommended.
Variable fonts
A variable font packs nombreux weights and styles (regular, bold, condensed, italic) into a unique fichier with adjustable axes. Que peut be a net win — un requête à la place of six — si vous en réalité utiliser several of ceux variants. But a complet variable font is a bigger unique fichier que un static weight, so si vous seulement ever render un weight, shipping the whole variable font peut be slower, pas faster. Subset it to the axes and characters vous utiliser, serve it as WOFF2 so it’s compressed, and vérifier the font’s license — pas every foundry permits subsetting or self-hosting.
Reducing the fichier in the premier placer
Everything ci-dessus manages quand the font loads. Vous pouvez aussi shrink ce que loads.
Font subsetting strips out glyphs vous don’t utiliser (an all-Latin site doesn’t besoin
Cyrillic and CJK ranges), and WOFF2 is the well-compressed format to serve. A
plus petit font fichier is plus probable to arrive à l’intérieur optional’s window and moins probable
to block LCP — subsetting and compression are the complementary lever to
font-display and preload, pas an alternative to les.
There’s aucun unique “correct” subset or universal byte-savings percentage ici, though — it dépend on the scripts, characters, and weights votre spécifique audience en réalité nécessite. A number vous saw in someone else’s cas study or benchmark isn’t a promise pour votre pages; mesurer votre propre font requêtes avant and après.
Is ce a ranking factor?
Be precise ici. Font chargement is pas a direct ranking factor. Ce que it affecte is
CLS and LCP, qui are Core Web Vitals and partie of Google’s page experience
signals. And page experience is a lightweight, tiebreaker-style signal — relevance
and quality dominate; it helps decide entre sinon comparable results, pas
entre a great page and a poor un. So the honest framing is: fix votre font chargement
parce que it’s a genuine user-experience problem que se produit to feed two ranking
inputs — pas parce que a font-display valeur va déplacer vous up le résultats on its propre.
My propre prendre
À travers my Ahrefs
CLS and
LCP guides I’ve landed on
the même priority order, and it encore holds. Si vous pouvez utiliser a system font, do que —
there’s nothing to charger, so là are aucun delays or changements que causer a shift. Si vous
have to utiliser a custom font, the current meilleur méthode pour minimizing CLS is to combine
<link rel="preload"> (grab the font as soon as possible) with font-display: optional (give it a petit window to charger); si it doesn’t faire it in temps, lune page
simplement montre a par défaut font, and votre custom font obtient mis en cache and montre up on
subsequent loads. Preload, alors optional, alors — meilleur of tout — simplement don’t utiliser a
custom font. That’s the whole ladder.
AI summary
A condensed prendre on the Avancé version:
- Font chargement = ce que le navigateur montre pendant que a custom font downloads. It’s a special cas parce que fonts are les deux an external resource and ils modifier text metrics — so ils peut hurt two Core Web Vitals at une fois.
- LCP: a render-blocking font que hides votre largest text element (FOIT) delays
LCP. Quelconque
font-displayvaleur autre queauto/blockgarde text visible so LCP isn’t blocked on the font. - CLS: the fallback-to-web-font swap reflows the layout. FOIT causes CLS aussi — invisible text is encore laid out in the fallback’s metrics, so the swap encore shifts.
font-displayis the principal lever:swap= FOUT (fast text, encore swaps);optional= ~100ms window alors commits, so aucun plus tard swap and aucun swap-related shift. web.dev suggests mixing les:swappour branding,optionalpour corps.- Preload fixes late font discovery. Preload +
font-display: optionalis Google’s singled-out combo pour eliminating layout jank (Chrome 83+). Don’t over-preload — it steals resources from autre loads. - Passing the Lighthouse font-display audit ≠ fixing CLS. The swap shift is a
separate fix: a metrically-matched fallback, or
size-adjust/ascent-override/descent-override/line-gap-override. - Google Fonts peut définir
font-displayvia the&display=URL parameter (aucun self-hosting nécessaire); self-hosting encore removes the supplémentaire connection hop. - Pas a direct ranking factor — it feeds CLS/LCP, qui are page experience signals (a tiebreaker). Meilleur fix of tout: utiliser a system font.
Documentation officielle
Primary-source documentation from Google and Bing.
- Meilleur Practices pour Fonts (web.dev) — the
font-displayvaleur table (block/swap periods) and the mix-strategy advice. - Optimize Décalage cumulatif de mise en page (web.dev) — the FOIT/FOUT explanation and pourquoi les deux causer layout shift.
- Optimize Plus grand affichage de contenu (web.dev) — quand a web font is the LCP resource and how
font-displaygarde text visible. - Prevent layout shifting and FOIT by preloading optional fonts (web.dev) — the preload +
font-display: optionalcombo and the Chrome 83 fix. - Optimize WebFont chargement and rendering (web.dev) — broader font-loading performances guide.
- Apprendre: Optimize web fonts (web.dev) — the structured lesson version.
- Garantir text remains visible during webfont charger (Chrome pour Developers) — the Lighthouse font-display audit. Remarque: as of Lighthouse 13 ce déplacé from a standalone audit into a broader “Font display insight” panel, so older screenshots and guides utiliser the old naming.
- Google Fonts CSS2 API —
displayparameter — settingfont-displayviune URL sans self-hosting. - MDN —
font-display— the CSS spec référence Google’s propre docs lien to pour valeur definitions.
Bing / Microsoft
- Fast Front-End Performances pour Microsoft Bing (Bing Search Quality Insights, Aug 2022) — documents font preloading as a production technique on Bing’s propre results pages. Remarque: ce post confirms the preload mechanism seulement; it doesn’t cover
font-display, FOIT/FOUT, CLS, or LCP by nom.
Quotes from the source
On-the-record statements from Google’s Chrome/web.dev docs and Bing engineering. Font
chargement lives in the rendering/performances spec area, so the principal sources ici are
the Chrome and web.dev teams (pas Search Relations) — là is aucun on-record Search
team quote appel font-display a ranking topic, and I’m pas going to invent un.
Google — web.dev (Chrome team)
- “Les deux approaches peut causer layout shifts. Même si the text is invisible, it’s encore laid out en utilisant the fallback font, so quand the web font loads, the text block and the surrounding content shift” — web.dev, Optimize Décalage cumulatif de mise en page. Jump to quote
- “The fallback font is swapped with the web font, incurring a Flash of Unstyled Text (FOUT). ‘Invisible’ text is affiché en utilisant the fallback font jusqu’à a web font is disponible and the text is made visible (FOIT—flash of invisible text).” — web.dev, Optimize Décalage cumulatif de mise en page. Jump to quote
- “Si vous définir a
font-displayvaleur of anything autre queautoorblock, alors text va toujours be visible during charger, and LCP won’t be blocked on an additional network requête.” — web.dev, Optimize Plus grand affichage de contenu. Jump to quote
Bing — preloading fonts in production
- Bing’s engineering team describes preload tags in the
<head>que tell the navigateur to commencer downloading its custom web fonts immédiatement; sans ceux tags, le navigateur wouldn’t récupérer the fonts jusqu’à it had parsed the CSS and encountered matching elements — so preloading rend les disponible in temps pour text rendering. Lire the post
#:~:text= deep liens jump straight to the quoted passage on the live page. Font-loading checklist
A rapide réussir to assurez-vous fonts aren’t quietly wrecking votre Core Web Vitals:
- Every custom
@font-face(or Google Fonts URL) sets a deliberatefont-displayvaleur — pas le navigateur par défaut. - Corps text uses
font-display: optional(or a metrically-matchedswap) to éviter a swap-driven layout shift. - The un or two fonts utilisé ci-dessus the fold are preloaded with
<link rel="preload" as="font" type="font/woff2" crossorigin>. - You’re pas preloading every weight — seulement what’s nécessaire pour the initial render.
- The preload’s
href,as="font",type, andcrossoriginmatch the réel@font-facerequête (vérifié in the Network panel) — aucun unused preload, aucun duplicate download. - Votre
font-familystack noms a sensible system fallback, pas simplement the custom font. - Si a swap encore shifts, fallback metrics are matched (
size-adjust,ascent-override,descent-override,line-gap-override). - Fonts are served as WOFF2 and subset to the characters/weights vous en réalité utiliser.
- Google Fonts embeds inclure a
displayparameter and apreconnecttofonts.gstatic.com. - Variable fonts are seulement utilisé quand vous render multiple variants — sinon a unique static weight may be lighter.
- You’ve confirmed with PageSpeed Insights / Lighthouse que fonts aren’t the LCP element or a CLS culprit.
The mental models
1. Fonts hit two vitals via two mechanisms.
LCP: a render-blocking font hides votre largest text element jusqu’à it loads. CLS: the
fallback→web-font swap changements text metrics and reflows. Fix les as two separate
problems, parce que un fix (swap) helps LCP but leaves CLS untouched.
2. FOIT vs. FOUT — les deux échouer, differently. FOIT (invisible jusqu’à chargé) risks a rendering delay → LCP. FOUT (fallback alors swap) risks a layout shift → CLS. Là is aucun “safe default”; vous have to choisir and mitigate.
3. The font-display decision.
optional = a ~100ms window, alors commit with aucun plus tard swap (meilleur pour CLS-sensitive
corps text). swap = montrer text now, guarantee the brand font eventually (meilleur pour
branding, accept a petit shift). Mix les per element plutôt que un valeur
everywhere.
4. Discovery vs. render.
Preload fixes discovery (le navigateur learns à propos de the font early). font-display
fixes render behavior (ce que montre pendant que it loads). Fallback-metric matching fixes
the shift itself. They’re three différent levers — vous souvent vouloir tout three.
5. The bon / meilleur / meilleur ladder.
Bon: preload votre fonts (meilleur encore, same-origin, to drop the supplémentaire connection).
Meilleur: font-display: optional, paired with preload, so a slow font simplement montre a
par défaut and caches pour suivant temps. Meilleur: utiliser a system font — nothing loads, so aucun
delay and aucun shift.
Font chargement — cheat sheet
font-display valeurs (block / swap periods, per web.dev):
| Valeur | Block | Swap | Bon pour |
|---|---|---|---|
auto | Browser-dependent | Browser-dependent | Nothing — it’s the unmanaged par défaut |
block | 2–3s | Infinite | Rarely — causes FOIT, risks LCP |
swap | 0ms | Infinite | Branding/headlines (fast text, but swaps → peut shift) |
fallback | 100ms | 3s | A compromise: brief block, limited swap window |
optional | 100ms | None | Corps text (aucun swap → aucun swap-driven CLS) |
Figures ci-dessus are web.dev’s documented Chromium behavior. The CSS spec itself seulement defines block/swap period categories (short, extremely petit, infinite, none) and leaves exact timing to le navigateur — vérifier current numbers pour le navigateur you’re testing.
The two échec modes
- FOIT = invisible jusqu’à chargé → risks delaying LCP.
- FOUT = fallback alors swap → risks a layout shift → CLS.
- Les deux causer CLS une fois the swap se produit; seulement fallback-metric matching or
optionalempêche it.
The fixes, in priority order
- Utiliser a system font (nothing loads).
- Preload the critical font (
as="font" type="font/woff2" crossorigin). - Définir
font-display(optionalpour corps,swappour branding). - Match the fallback’s metrics (
size-adjust,ascent-override,descent-override,line-gap-override). - Subset + WOFF2 to shrink the fichier itself.
Google Fonts fast facts
- Ajouter
&display=swap(oroptional/fallback) to the CSS2 URL to définirfont-displaysans self-hosting. - Encore a render-blocking stylesheet + a separate font requête — ajouter
preconnecttofonts.gstatic.com. - Self-hosting removes the supplémentaire DNS/connection hop.
Diagnose
- PageSpeed Insights / Lighthouse “Font display insight” (was the standalone “Garantir text remains visible during webfont charger” audit avant Lighthouse 13).
- Chrome DevTools Performances + Network panels — voir quand fonts charger relative to premier paint and shifts.
Font-loading myths and mistakes
Chaque of ces is a réel, courant audit finding — with pourquoi it’s incorrect and Que faire à la place.
“font-display: swap fully solves my CLS problem.”
Pourquoi it’s incorrect: swap fixes FOIT (text is visible immédiatement, bon pour LCP and
the Lighthouse audit) but it guarantees FOUT — and si the fallback and web font
differ in size, the swap encore shifts the layout. Google’s Lighthouse docs remarque FOIT
and FOUT have the même impact on CLS une fois the swap se produit.
Do à la place: pair it with a metrically-matched fallback (or utiliser optional), so the
swap doesn’t déplacer anything.
“Preloading a font always speeds up my page.” Pourquoi it’s incorrect: web.dev is explicit que preload comes at the cost of taking navigateur resources away from chargement autre resources. Preloading fonts vous don’t besoin ci-dessus the fold delays plus important fonctionner. Do à la place: preload seulement the un or two fonts nécessaire pour the initial render.
“font-display: optional means the custom font never loads.”
Pourquoi it’s incorrect: it loads and is mis en cache — it’s simplement pas utilisé on que spécifique page
charger si it misses the ~100ms window. Une fois mis en cache, plus tard page views typically montrer it
immédiatement.
Do à la place: utiliser optional pour CLS-sensitive corps text sans worrying que
returning visitors miss the brand font.
“Quelconque font-display valeur fixes the Lighthouse ‘invisible text’ warning, so I’m
fait.”
Pourquoi it’s incorrect: passing que audit is necessary but pas sufficient — the swap
layout shift is a separate, related-but-distinct problem.
Do à la place: après clearing the audit, vérifier CLS and fix the fallback metrics si the
swap encore shifts.
“Google Fonts are auto-optimized and can’t cause CWV problems.”
Pourquoi it’s incorrect: a copy-pasted Google Fonts embed is encore a render-blocking
stylesheet requête plus a separate font requête unless display and
preconnect/preload are configuré. “It’s from Google so it’s fine” is a courant
real-world audit miss.
Do à la place: ajouter &display=, preconnect to fonts.gstatic.com, and preload the
critical weight.
“Font loading is a UX-only concern with no SEO relevance.” Pourquoi it’s incorrect: CLS and LCP are Core Web Vitals and partie of Google’s page experience signals. Font choices sit directement in a SEO technique’s remit. Do à la place: treat font chargement as partie of votre CWV fonctionner — pendant que keeping it in proportion (page experience is a tiebreaker, pas a principal factor).
Trouver the fonts chargement on une page
A rapide DevTools Console snippet to liste every font face le navigateur en réalité chargé, and si chaque is fait — utile pour spotting a heavy or slow font.
Chrome DevTools Console
// List loaded font faces and their status
[...document.fonts].map(f => ({
family: f.family,
weight: f.weight,
style: f.style,
status: f.status, // "loaded", "loading", "unloaded", "error"
display: f.display, // the font-display value in effect
}));
// When did fonts finish loading? (relative to navigation start)
document.fonts.ready.then(() =>
console.log("All fonts ready at", performance.now().toFixed(0), "ms")
);Watch pour font-driven layout shifts
Paste ce in the Console to log CLS entries as ils se produire, notamment the elements que déplacé — handy pour confirming a font swap is the culprit.
Chrome DevTools Console
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log("Layout shift", entry.value.toFixed(4),
entry.sources?.map(s => s.node));
}
}
}).observe({ type: "layout-shift", buffered: true });Vérifier que a font fichier is WOFF2 and reasonably sized
Fonts devrait be WOFF2 and subset. Point ces at a font URL to vérifier its size and type.
macOS / Linux
curl -sI https://example.com/fonts/brand.woff2 \
| grep -iE "content-type|content-length"Windows / PowerShell
$r = Invoke-WebRequest -Method Head https://example.com/fonts/brand.woff2
$r.Headers["Content-Type"]; $r.Headers["Content-Length"]A grand content-length (bien into the hundreds of KB pour a unique weight) is a
subsetting/compression opportunity.
Qui font-loading strategy fits lune page?
How should the critical text font load?
Prove a font-loading modifier worked
Critical-font preload tester
Tester to run: reload with cache disabled and inspect the font request’s initiator and commencer temps in the Network panel. Attendu result: the intended critical font starts early and is reused by CSS sans a duplicate download. Échec interpretation: the preload attributes ne faites pas match the CSS requête or the font n’est pas en réalité critical. Monitoring window: immediate. Rollback trigger: duplicate requêtes, console errors, or contention que delays plus important resources.
Font-swap stability tester
Tester to run: throttle the charger pendant que recording the Performances panel Layout Shifts track. Attendu result: fallback text remains visible and the final font ne fait pas créer a measurable shift. Échec interpretation: fallback metrics encore differ or the swap se produit aussi late. Monitoring window: immediate à travers pris en charge breakpoints. Rollback trigger: hidden text, clipped text, or worse CLS.
Field-vitals tester
Tester to run: comparer post-release LCP and CLS pour the modifié template with the prior RUM baseline. Attendu result: the targeted metric improves sans degrading the autre. Échec interpretation: the font was pas the bottleneck or the strategy traded chargement speed pour instability. Monitoring window: RUM as trafic arrives; CrUX over its rolling window. Rollback trigger: soit field metric worsens consistently.
Ressources utiles
My connexe writing
- Ce que Is Décalage cumulatif de mise en page (CLS) & How To Améliorer It (Ahrefs) — my CLS guide, notamment the preload +
font-display: optionalfix pour font-driven shifts. - Ce que Is Plus grand affichage de contenu (LCP) & How To Améliorer It (Ahrefs) — the bon/meilleur/meilleur font ladder pour LCP.
- Ce que Are Core Web Vitals (CWVs) & How To Améliorer Les (Ahrefs) — où CLS and LCP fit in the bigger CWV picture.
- Patrick Stox on the Ahrefs blog — the rest of my SEO technique writing.
From autour the industry
- Fixing Layout Shifts Caused by Web Fonts (DebugBear, Umar Hansa) — end-to-end: mesurer → trouver the font →
font-display→ meilleur fallback → adjust metrics. - Garantir text remains visible during webfont charger (DebugBear) — the Lighthouse-audit-specific troubleshooting angle.
- How to éviter layout shifts caused by web fonts (Simon Hearne) — a practitioner-level deep dive.
- FOUT, FOIT, FOFT (CSS-Tricks) — the canonical explainer pour the terminology.
- A Nouveau Façon To Reduce Font Chargement Impact: CSS Font Descriptors (Smashing Magazine) — the
size-adjust/ascent-override/descent-override/line-gap-overridetechnique in depth. - How to Reduce Layout Reflow Quand En utilisant Web Fonts (Material Design) — a practical CSS-descriptor walkthrough from Google’s Material team.
- We shipped font-display to Google Fonts (Addy Osmani) — the
displayURL parameter and pourquoi it supprimé the besoin to self-host pourfont-displaycontrôler.
Testez vos connaissances: Font Chargement
Five rapide questions on how web fonts affecter Core Web Vitals. Pick an réponse pour chaque, alors vérifier.
Journal des modifications
Mis à jour le 17 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.