暫定日本語訳:Font Loading

暫定日本語訳:How web font loading affects Core Web Vitals like CLS and LCP, font-display strategies, preloading fonts, and reducing layout shift from font swaps.

初回公開:2026年7月2日 · 最終更新:2026年8月4日 · Advanced
言語

暫定日本語訳:Custom web fonts are external files that have to download before text can render in them, so the browser needs a plan for what to show in the meantime. That plan — set mainly by the CSS font-display property — moves two Core Web Vitals: LCP (when a render-blocking font delays your largest text) and CLS (when swapping the fallback for the web font shifts the layout). The two default behaviors, FOIT and FOUT, each have a failure mode. The reliable fixes: preload critical fonts, use font-display: optional or swap deliberately, match your fallback font's metrics, or skip custom fonts entirely. It's not a direct ranking factor — it feeds CLS/LCP, which are ページ experience signals.

暫定日本語案: TL;DR — Custom web fonts are render-affecting external resources. They hit 暫定日本語案: LCP when a render-blocking font delays your largest text element, and CLS 暫定日本語案: when the fallback-to-web-font swap reflows the layout. The two default behaviors — 暫定日本語案: FOIT (invisible until loaded) and FOUT (fallback then swap) — each fail 暫定日本語案: differently. font-display is the primary lever (swap guarantees FOUT; 暫定日本語案: optional gives a ~100ms window and then commits, killing the later swap). 暫定日本語案: Preloading fixes late font discovery; preload + font-display: optional is 暫定日本語案: the combo Google’s own engineering singled out for eliminating layout jank. But 暫定日本語案: passing the Lighthouse font-display check doesn’t fix CLS — that needs a 暫定日本語案: metrically-matched fallback (or size-adjust/ascent-override overrides). None of 暫定日本語案: this is a direct ranking factor; it feeds CLS/LCP, which are ページ 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-display

暫定日本語案: Why fonts are a special case

暫定日本語案: Most パフォーマンス problems are about bytes — an image is too big, a script blocks 暫定日本語案: the main thread. Fonts are worse than that in one specific way: they’re an external 暫定日本語案: resource and they change the metrics of your text. So a font can hurt you two 暫定日本語案: different ways at once. It can delay when text paints (an LCP problem), and it can 暫定日本語案: change the size and shape of that text after it’s already on screen (a CLS problem).

暫定日本語案: The two default browser behaviors are worth naming because the whole topic hangs off 暫定日本語案: them:

  • 暫定日本語案: FOIT (Flash of Invisible Text): text in the custom font is rendered invisible 暫定日本語案: until the font loads or a timeout is hit — historically up to a ~3-second block in 暫定日本語案: most browsers.
  • 暫定日本語案: FOUT (Flash of Unstyled Text): the fallback font shows immediately, then gets 暫定日本語案: swapped for the web font once it loads.

暫定日本語案: FOIT feels “cleaner” (no 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 also helps to separate the pipeline into distinct stages, because success at one 暫定日本語案: stage doesn’t guarantee success at the next. A @font-face rule only declares a 暫定日本語案: face — the browser fetches the actual font file only once matching styled text on 暫定日本語案: the ページ requires it (declaration and matching are separate steps from the fetch). 暫定日本語案: That fetch is subject to CORS if the font is served cross-origin, so a stylesheet 暫定日本語案: that loads cleanly doesn’t guarantee the font response itself carries the right 暫定日本語案: cross-origin permission — a missing header there fails silently as a font that 暫定日本語案: never renders. And a successful fetch still doesn’t guarantee a stable-looking ページ: 暫定日本語案: cold-cache, warm-cache, and already-cached font states can produce different 暫定日本語案: discovery and swap timing, so testing one repeat ページ load in DevTools doesn’t tell 暫定日本語案: you what a first-time visitor actually sees.

暫定日本語案: How fonts affect LCP

暫定日本語案: If the largest visible element on your ページ is text — a big headline, a hero 暫定日本語案: paragraph — then the font that text uses can become part of your LCP path. Per 暫定日本語案: web.dev’s LCP guidance, the LCP resource of a ページ, if it has one, will be either an 暫定日本語案: image or a web font. A render-blocking font that leaves that text invisible (FOIT) 暫定日本語案: pushes your LCP out until the font arrives.

暫定日本語案: The fix here is straightforward and comes straight from Google. On web.dev’s 暫定日本語案: Optimize Largest Contentful Paint guide:

暫定日本語案: “If you set a font-display value of anything other than auto or block, then 暫定日本語案: text will always be visible during load, and LCP won’t be blocked on an additional 暫定日本語案: network request.” 暫定日本語案: — web.dev

暫定日本語案: In other words: swap, fallback, or optional all keep text visible during load, 暫定日本語案: so your LCP isn’t hostage to the font request.

暫定日本語案: How fonts affect CLS

暫定日本語案: CLS comes from the swap. Your fallback font and your web font almost never have 暫定日本語案: identical character widths and line heights, so when the browser replaces one with 暫定日本語案: the other, the text reflows — and everything below it moves. That’s a layout shift.

暫定日本語案: The counterintuitive part, and the thing most people miss: FOIT causes CLS too. 暫定日本語案: Even invisible text is still laid out using the fallback font’s metrics, so the swap 暫定日本語案: still moves things. From web.dev’s 暫定日本語案: Optimize Cumulative Layout Shift guide:

暫定日本語案: “Both approaches can cause layout shifts. Even if the text is invisible, it’s 暫定日本語案: still laid out using the fallback font, so when the web font loads, the text block 暫定日本語案: and the surrounding コンテンツ shift” 暫定日本語案: — web.dev

暫定日本語案: The same ページ frames the two behaviors plainly:

暫定日本語案: “The fallback font is swapped with the web font, incurring a Flash of Unstyled 暫定日本語案: Text (FOUT). ‘Invisible’ text is displayed using the fallback font until a web 暫定日本語案: font is available and the text is made visible (FOIT—flash of invisible text).” 暫定日本語案: — web.dev

暫定日本語案: I’ve said the same thing in plainer terms in my Ahrefs write-up on 暫定日本語案: Cumulative Layout Shift: 暫定日本語案: when a font loads or changes, you end up with a noticeable shift — a FOIT or a FOUT. 暫定日本語案: It’s one of the most common real-world CLS causes, right alongside images without 暫定日本語案: dimensions and コンテンツ injected after load.

暫定日本語案: The font-display property

暫定日本語案: font-display is a @font-face descriptor that controls two windows: the block 暫定日本語案: period (how long the browser hides text waiting for the font) and the swap 暫定日本語案: period (how long, after the block period, it will still swap in the web font once 暫定日本語案: it arrives). Per web.dev’s Best Practices for Fonts:

ValueBlock periodSwap period
autoBrowser-dependentBrowser-dependent
block2–3 secondsInfinite
swap0msInfinite
fallback100ms3 seconds
optional100msNone

暫定日本語案: MDN’s font-display reference, 暫定日本語案: which Google’s own docs リンク to as the spec source, describes them tersely: swap 暫定日本語案: gives an extremely small block period and an infinite swap period; optional gives 暫定日本語案: an extremely small block period and no swap period. That “no swap period” is the 暫定日本語案: whole point of optional — after the block period window closes, whatever font is 暫定日本語案: in use stays, so there’s no later swap to shift the layout.

暫定日本語案: One caution on the numbers in that table: the CSS specification itself only defines 暫定日本語案: block/swap period categories — short, extremely small, infinite, none — and 暫定日本語案: leaves the exact duration to the browser. The millisecond/second figures above are 暫定日本語案: web.dev’s documented Chromium behavior, not a cross-browser guarantee. Treat them as 暫定日本語案: illustrative rather than a spec promise, and check current numbers for whichever 暫定日本語案: browser/version you’re actually testing against.

暫定日本語案: Which value for which コンテンツ? web.dev’s own advice is that these can be mixed: 暫定日本語案: use swap for branding and other visually distinctive elements (where seeing the 暫定日本語案: brand font matters and a brief shift is acceptable), and optional for body text 暫定日本語案: (where CLS-sensitivity wins and you’d rather not shift). That’s a genuinely useful 暫定日本語案: rule of thumb — don’t apply one value サイト-wide by reflex.

暫定日本語案: Preloading fonts

暫定日本語案: Font requests are discovered late. The browser doesn’t know it needs a font until 暫定日本語案: it has parsed your CSS, matched a @font-face rule to an element on the ページ, and 暫定日本語案: decided that element is visible. Only then does it start the download. A 暫定日本語案: <link rel="preload"> short-circuits that:

<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>

暫定日本語案: That tells the browser to start fetching the font immediately, in parallel with 暫定日本語案: everything else, instead of waiting to discover it. Bing’s engineering team 暫定日本語案: describes exactly this mechanism on their own 検索 ページ (more in the Quotes tab): 暫定日本語案: the preload tags in the <head> kick off the font downloads right away, whereas 暫定日本語案: without them the browser wouldn’t fetch the fonts until it had parsed the CSS and 暫定日本語案: found matching elements.

暫定日本語案: The strongest combination per Google’s own 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 most 暫定日本語案: effective way to guarantee no layout jank when rendering custom fonts, and notes 暫定日本語案: that Chrome (from version 83) eliminated the layout shifting that used to happen when 暫定日本語案: preloading optional fonts. The preload gives the font its best shot at arriving 暫定日本語案: inside the ~100ms window; optional guarantees that if it doesn’t, you don’t pay for 暫定日本語案: it with a shift.

暫定日本語案: When not to preload. Preloading isn’t free. web.dev warns that preload is 暫定日本語案: highly effective at making fonts discoverable early, but it comes at the cost of 暫定日本語案: taking browser resources away from loading other resources. Preload the one or two 暫定日本語案: fonts you actually need above the fold — preloading every font weight you own can 暫定日本語案: starve more important resources and make the ページ slower overall.

暫定日本語案: Make sure the preload actually gets reused. A preload only helps if the browser 暫定日本語案: can match it to the real font request — the href, as="font", type, and 暫定日本語案: crossorigin mode all have to line up with what the CSS @font-face rule ends up 暫定日本語案: requesting, or you’ll get an “unused preload” warning and a wasted second download 暫定日本語案: instead of a faster one. Preloading can also bypass unicode-range selection, 暫定日本語案: pulling down a subset you didn’t actually need for that ページ. Confirm the match in 暫定日本語案: DevTools’ Network panel: you want to see one request for that font, kicked off by 暫定日本語案: the preload, not two.

暫定日本語案: Fixing the shift itself: fallback metric matching

暫定日本語案: Here’s the trap: passing the Lighthouse font-display check does not fix CLS. 暫定日本語案: Google’s Lighthouse docs are explicit that FOIT and FOUT have the same impact on CLS 暫定日本語案: once the custom font replaces the temporary system font. So swap makes your text 暫定日本語案: visible (good for LCP and for the “invisible text” audit) but leaves the swap shift 暫定日本語案: in place.

暫定日本語案: To kill the shift when a swap does happen, you have to make the fallback font and 暫定日本語案: the web font take up the same space. Two levers:

  1. 暫定日本語案: Pick a metrically-similar system fallback in your font-family stack, rather 暫定日本語案: than a single custom font name with nothing sensible behind it. The closer the 暫定日本語案: fallback’s character widths and line height are to the web font, the smaller the 暫定日本語案: shift.
  2. 暫定日本語案: Override the web font’s metrics with size-adjust, ascent-override, 暫定日本語案: descent-override, and line-gap-override on the @font-face rule, so the web 暫定日本語案: font is forced to match the fallback’s box. web.dev lists these descriptors, and 暫定日本語案: Smashing Magazine’s 暫定日本語案: deep dive on CSS font descriptors 暫定日本語案: walks through them in detail if you want to go all the way.

暫定日本語案: Each of those four descriptors adjusts a different metric, and current browser 暫定日本語案: support varies by descriptor — check compatibility before leaning on any single one. 暫定日本語案: Validate against the actual weights, styles, and scripts you ship, too: a fix 暫定日本語案: confirmed on your regular-weight Latin text doesn’t guarantee bold, italic, or a 暫定日本語案: non-Latin script behave the same way.

暫定日本語案: DebugBear’s 暫定日本語案: Fixing Layout Shifts Caused by Web Fonts 暫定日本語案: is a good end-to-end walkthrough of this: measure the impact, identify the problem 暫定日本語案: font, apply font-display, choose a better fallback, then adjust font metrics.

暫定日本語案: Google Fonts vs. self-hosting

暫定日本語案: You don’t have to self-host to control font-display. The 暫定日本語案: Google Fonts CSS2 API accepts a 暫定日本語案: display query parameter — https://fonts.googleapis.com/css2?family=Roboto&display=swap 暫定日本語案: sets font-display directly on the served @font-face rules. Addy Osmani’s 暫定日本語案: post on shipping font-display to Google Fonts 暫定日本語案: covers the change: previously the only way to specify font-display for Google 暫定日本語案: Fonts was to self-host them, and this removed that need.

暫定日本語案: Self-hosting still wins on one thing: it eliminates the extra DNS lookup and 暫定日本語案: connection to fonts.googleapis.com and fonts.gstatic.com. That’s a real latency 暫定日本語案: cost, and one of the reasons a 暫定日本語案: preconnect resource hint to those 暫定日本語案: origins helps if you do use Google Fonts. Weigh the connection overhead against the 暫定日本語案: convenience — and don’t assume “it’s from Google, so it’s fine.” A copy-pasted Google 暫定日本語案: Fonts embed is still a render-blocking stylesheet request plus a font request, and 暫定日本語案: older embeds may not carry a display value at all.

暫定日本語案: There’s no universal winner between the two options — it comes down to which scripts 暫定日本語案: and weights you actually ship, your caching setup, and the font’s license terms. Run 暫定日本語案: the comparison against your own ページ rather than defaulting to whichever one a 暫定日本語案: tutorial recommended.

暫定日本語案: Variable fonts

暫定日本語案: A variable font packs many weights and styles (regular, bold, condensed, italic) 暫定日本語案: into a single file with adjustable axes. That can be a net win — one request instead 暫定日本語案: of six — if you actually use several of those variants. But a full variable font is a 暫定日本語案: bigger single file than one static weight, so if you only ever render one weight, 暫定日本語案: shipping the whole variable font can be slower, not faster. Subset it to the axes 暫定日本語案: and characters you use, serve it as WOFF2 so it’s compressed, and check the font’s 暫定日本語案: license — not every foundry permits subsetting or self-hosting.

暫定日本語案: Reducing the file in the first place

暫定日本語案: Everything above manages when the font loads. You can also shrink what loads. 暫定日本語案: Font subsetting strips out glyphs you don’t use (an all-Latin サイト doesn’t need 暫定日本語案: Cyrillic and CJK ranges), and WOFF2 is the well-compressed format to serve. A 暫定日本語案: smaller font file is more likely to arrive inside optional’s window and less likely 暫定日本語案: to block LCP — subsetting and compression are the complementary lever to 暫定日本語案: font-display and preload, not an alternative to them.

暫定日本語案: There’s no single “correct” subset or universal byte-savings percentage here, though 暫定日本語案: — it depends on the scripts, characters, and weights your specific audience actually 暫定日本語案: needs. A number you saw in someone else’s case study or benchmark isn’t a promise for 暫定日本語案: your ページ; measure your own font requests before and after.

暫定日本語案: Is this a ranking factor?

暫定日本語案: Be precise here. Font loading is not a direct ranking factor. What it affects is 暫定日本語案: CLS and LCP, which are Core Web Vitals and part of Google’s ページ experience 暫定日本語案: signals. And ページ experience is a lightweight, tiebreaker-style signal — relevance 暫定日本語案: and quality dominate; it helps decide between otherwise comparable results, not 暫定日本語案: between a great ページ and a poor one. So the honest framing is: fix your font loading 暫定日本語案: because it’s a genuine user-experience problem that happens to feed two ranking 暫定日本語案: inputs — not because a font-display value will move you up the results on its own.

暫定日本語案: My own take

暫定日本語案: Across my Ahrefs 暫定日本語案: CLS and 暫定日本語案: LCP guides I’ve landed on 暫定日本語案: the same priority order, and it still holds. If you can use a system font, do that — 暫定日本語案: there’s nothing to load, so there are no delays or changes that cause a shift. If you 暫定日本語案: have to use a custom font, the current best method for minimizing CLS is to combine 暫定日本語案: <link rel="preload"> (grab the font as soon as possible) with font-display: 暫定日本語案: optional (give it a small window to load); if it doesn’t make it in time, the ページ 暫定日本語案: just shows a default font, and your custom font gets cached and shows up on 暫定日本語案: subsequent loads. Preload, then optional, then — best of all — just don’t use a 暫定日本語案: custom font. That’s the whole ladder.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.