The four font-display options
font-display is the CSS descriptor inside @font-face that tells the browser how to behave while a web font is loading. The four useful values are swap, fallback, optional, and block. swap shows the fallback immediately and swaps to the web font when it loads. fallback shows the fallback after 100ms then swaps if the font loads within 3 seconds. optional only uses the font if it loads in under 100ms. block hides text for up to 3 seconds waiting for the font.
swap is the most common default because it never hides text. The downside is the visual swap when the font arrives, which causes layout shift. fallback is the most performance-conscious choice for body text because it prefers the fallback if the font is slow. optional is the only choice for fonts that are not critical to the brand, because it never blocks rendering and never triggers a swap on slow connections.
When to use preload
preload is a <link> tag that tells the browser to start downloading a font as soon as the HTML is parsed, before the CSS that declares the @font-face block has even been read. This eliminates the discovery delay where the browser would otherwise wait until layout to know the font is needed.
Preload only the one or two most critical fonts: the body weight and the hero weight, typically. Preloading every weight defeats the purpose by competing with other critical resources. The Strategy generator includes the rel=preload tag with the right as and crossorigin attributes, plus the matching @font-face block, so they line up correctly.
Common Use Cases
Performance engineers chasing a green Lighthouse score use the Strategy to pick font-display: optional for blog post body and font-display: swap for the hero headline. E-commerce sites where CLS is monitored use it to verify their swap target is metric-compatible with the primary. Marketing teams shipping a new brand font use it to generate the production-ready CSS without copying boilerplate from Stack Overflow.
Documentation sites self-hosting Google Fonts use the Strategy to assemble the @font-face block with the right unicode-range subsets, so a user only downloads the Latin subset by default and never pays for Cyrillic or Arabic glyphs they will not see.
How We Compare
Most font-loading tutorials walk you through a single example and leave you to assemble the production code. The Strategy generator does the assembly: pick your goals (no CLS, fastest first paint, brand-perfect render), and it outputs the complete @font-face block, preload tags, and recommended font-display value, ready to paste.
Compared to letting Google Fonts auto-generate the link tag, the Strategy here lets you choose a self-hosted setup with full control over subsets, formats, and unicode-range. Self-hosting trims about 100 milliseconds off the critical path on most pages because there is no extra DNS lookup.
Frequently Asked Questions
What is the difference between FOIT and FOUT?
FOIT is Flash of Invisible Text, where the browser hides text completely while waiting for a web font to load. The block phase of font-display: block causes this. FOUT is Flash of Unstyled Text, where the browser shows fallback text immediately and swaps to the web font when it arrives. font-display: swap causes this. FOUT is generally preferred because content is always readable; FOIT can hide the page during slow loads.
Which font-display value should I pick?
swap for headlines and brand-critical text where readability matters more than visual consistency. fallback for body text where you want to prefer the fallback on slow connections. optional for decorative fonts that are not essential. block almost never. The Strategy generator includes a decision tree that asks about your use case and recommends one of these four.
How does preload affect critical path?
preload starts the font download in parallel with the HTML parse, removing the wait time between CSS parse and font discovery. On a fast connection this saves 50 to 150 milliseconds; on a slow connection it can save much more. The trade-off is that preloaded fonts compete with other critical resources for bandwidth, so preload sparingly: one or two fonts at most, never the whole family.
Do I need crossorigin on the preload tag?
Yes, always. Web fonts are loaded as cross-origin resources even when self-hosted, because the CSS @font-face spec treats them that way. Without crossorigin on the preload tag, the browser downloads the font twice: once for the preload (mode no-cors) and once for the actual font request (mode cors). Adding crossorigin to the preload tag makes them match.
Should I self-host or use Google Fonts CDN?
Self-host for performance, Google Fonts CDN for convenience. Self-hosting trims 50 to 200 milliseconds by removing the DNS lookup and TCP handshake to fonts.gstatic.com. Self-hosting also lets you ship only the subsets and weights you actually use. The trade-off is the build setup. For brand-critical sites, self-host. For prototypes and small marketing pages, the CDN is fine.
What is unicode-range and should I use it?
unicode-range is a descriptor inside @font-face that tells the browser to download a font file only if the page contains characters in that range. Splitting a font into Latin, Latin Extended, Cyrillic, and other subsets means a Latin-only page only downloads the Latin file. This is how Google Fonts ships fonts internally. The Strategy generator includes the recommended unicode-range values for the common Google Fonts subsets.
Will font-display: optional skip my font on every reload?
Only on the first visit when the font is not cached. font-display: optional gives the browser 100 milliseconds to download the font before painting. If it does not arrive, the page renders with the fallback and the font is downloaded in the background for the next visit. Repeat visits get the font from cache instantly. This is why optional works well for personalization tokens that build affinity over multiple sessions.
Does font-display work with variable fonts?
Yes, identically. font-display is a property of the @font-face declaration, not of the font file. A variable font ships as one file but is declared with one @font-face block (or several, one per font-style). Each block has its own font-display value. The Strategy generator handles variable fonts the same way it handles static ones, with a checkbox to declare the font-weight and font-stretch ranges.