How to fout vs foit: understanding font loading behaviour
- Step 1Decide whether FOUT or FOIT is worse for this surface — For prose, FOUT wins — readers can start reading immediately in the fallback. For a logo where the wrong font misrepresents the brand for a beat, you still usually want FOUT (`swap`) because invisible logo text is worse. For an icon font, FOIT (`block`) can win because fallback glyphs are meaningless. Make this call per `@font-face`.
- Step 2Translate the decision into a use case — In the **Use case** select above: choose **Brand-critical** for pure FOUT (`swap`), **Performance-critical** for the brief-FOIT-then-fallback behaviour of `optional`, or **Balanced** which also emits `swap`. There is one control; that is the whole input.
- Step 3Generate the annotated skeleton — Press **Generate**. The output explains the flash behaviour of all five values, then prints `Your choice for a <use case> workflow: font-display: <value>;` and a minimal `@font-face` block. Nothing is uploaded — the tool only formats text in your browser.
- Step 4Apply the value to your real font face — Copy the `font-display:` line into your production `@font-face`. The skeleton's `font-family: "YourFont"` and `src: "/fonts/yourfont.woff2"` are placeholders. For complete blocks with real paths and formats, use the [font-face generator](/font-tools/font-face-generator).
- Step 5Shrink the flash by preloading — Both FOUT (`swap`) and brief-FOIT (`fallback`/`optional`) windows are shorter when the font arrives sooner. Generate a preload tag with the [preload tag builder](/font-tools/preload-tag-builder) and put it in `<head>` so the fetch begins before the CSS is parsed.
- Step 6Observe the actual flash under throttling — DevTools → Network → Slow 4G → hard reload. `swap` shows fallback then a visible flash to the web font (FOUT). `block`/`auto` show blank text first (FOIT). `optional` shows the fallback and usually never swaps on the throttled first load. Confirm the flash you see matches the one you intended.
Which font-display value produces which flash
FOIT = invisible text while loading. FOUT = fallback shown, then swap. Some values produce a short FOIT followed by FOUT-style behaviour. Durations are spec guidance; engines vary.
| Value | Flash produced | What the visitor sees | Verdict for prose |
|---|---|---|---|
auto | FOIT (≈block) | Up to ~3s of invisible text, then the web font | Avoid — unpredictable, worst-case blank |
block | FOIT (long) | ~3s invisible, then the font swaps in even if late | Avoid for text; OK for icon fonts |
swap | FOUT (pure) | Fallback immediately, flash to the web font when it loads | Best for brand/headlines |
fallback | Brief FOIT then FOUT-ish | ~100ms blank, fallback ~3s, swap only if loaded in time | Good for body where late swap is unwanted |
optional | Brief FOIT then mostly fallback | ~100ms blank, then fallback; web font only if near-instant | Best for performance-critical body |
FOUT vs FOIT trade-offs
Why FOUT is usually the lesser evil, and the narrow case where FOIT wins.
| Dimension | FOUT (swap) | FOIT (block / auto) |
|---|---|---|
| Time to readable text | Immediate (fallback shown at once) | Delayed up to ~3s (blank until font arrives) |
| Layout stability | Reflow when the swap happens (CLS risk) | No mid-load reflow, but a late pop-in |
| Core Web Vitals | Helps LCP/FCP (text paints early); watch CLS | Hurts LCP/FCP (text paints late) |
| Brand fidelity on first paint | Wrong font briefly, then correct | No text, then correct |
| Best fit | Text, headlines, logos | Icon fonts where fallback glyphs are meaningless |
Cookbook
Snippets showing which value yields which flash. The picker emits the value; these show it in context. For full multi-format blocks see the font-face generator.
Pure FOUT for a headline — swap
Exampleswap shows the fallback instantly and always flashes to the web font when it arrives. This is pure FOUT: the visitor reads immediately, and the brand font replaces the fallback shortly after. The picker's Brand-critical and Balanced modes both emit this.
@font-face {
font-family: "YourFont";
src: url("/fonts/yourfont.woff2") format("woff2");
font-display: swap; /* FOUT: fallback now, web font later */
}Brief FOIT then fallback — optional
Exampleoptional gives ~100ms of invisible text (a brief FOIT), then renders the fallback. The web font only appears if it is cached or near-instant — otherwise no FOUT flash at all for the session. Performance-critical mode emits this.
@font-face {
font-family: "YourFont";
src: url("/fonts/yourfont.woff2") format("woff2");
font-display: optional; /* brief FOIT, then fallback, rarely swaps */
}Long FOIT, on purpose — block (icon fonts)
Exampleblock gives the longest FOIT (~3s invisible). For real text this is bad. For an icon font it can be correct: a fallback glyph would render as a meaningless box, so showing nothing briefly is the lesser evil. The picker never emits block — set it by hand.
@font-face {
font-family: "YourIcons";
src: url("/fonts/icons.woff2") format("woff2");
font-display: block; /* FOIT — defensible only for icon fonts */
}Avoiding the unpredictable default — auto
Exampleauto produces FOIT on most engines but is not guaranteed. Replacing auto with an explicit value makes the flash the same in every browser. This before/after is the single most common font-display fix.
/* Before: browser-default FOIT, varies by engine */
@font-face {
font-family: "YourFont";
src: url("/fonts/yourfont.woff2") format("woff2");
font-display: auto;
}
/* After: explicit FOUT, identical everywhere */
@font-face {
font-family: "YourFont";
src: url("/fonts/yourfont.woff2") format("woff2");
font-display: swap;
}Shrinking the FOUT flash with preload
ExampleThe FOUT swap is less jarring the sooner the font arrives. Preloading starts the fetch before the CSS that references it is parsed. Pair the swap value with a preload tag from the preload tag builder.
<!-- in <head>, before the stylesheet that defines @font-face -->
<link rel="preload" href="/fonts/yourfont.woff2" as="font"
type="font/woff2" crossorigin>
/* the rule still uses swap for FOUT */
@font-face {
font-family: "YourFont";
src: url("/fonts/yourfont.woff2") format("woff2");
font-display: swap;
}Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
FOUT reflow counts against Cumulative Layout Shift
Mitigate separatelyThe swap in FOUT can shift layout if the fallback and web font have different metrics, and that shift counts toward CLS. font-display does not fix this — size-adjust, ascent-override, and descent-override do, by matching the fallback's box to the web font. Pick a metrically-similar fallback or add the override descriptors; the picker does not emit them.
FOIT can fully hide above-the-fold text for seconds
AvoidWith block or auto on a slow connection, the largest text block on the page can be invisible for up to ~3s. That delays Largest Contentful Paint and leaves the visitor staring at a blank hero. This is the core argument for FOUT over FOIT for any real text. Reserve FOIT for icon fonts.
optional usually shows zero FOUT on the first visit
ExpectedAfter its ~100ms FOIT window, optional renders the fallback and only uses the web font if it is already cached. On an uncached first load it normally never swaps, so there is no FOUT flash at all — the visitor sees the fallback for the whole session while the font caches for next time. Great for reading comfort; means first-time visitors may not see your brand font.
auto's flash differs between Chrome, Firefox, and Safari
Unpredictableauto resolves to the engine default, which is roughly block/FOIT today but has changed between versions and differs in subtle ways across engines. If you want the same flash everywhere, never ship auto — name swap, fallback, or optional. The picker always recommends an explicit value.
Fallback font metrics make FOUT look worse than it is
Tune the fallbackA FOUT where Arial (the fallback) is much narrower than your web font produces a big visible jump. Choosing a fallback with similar x-height and advance widths, or using size-adjust, makes the same swap flash nearly invisible. The flash is unavoidable with swap; its magnitude is yours to control.
block on real text fails Lighthouse's font-display audit
Audit warningLighthouse flags @font-face rules that risk invisible text — block and auto typically trip the 'Ensure text remains visible during webfont load' audit. Switching to swap (FOUT) clears it. The picker's recommendations (swap/optional) are audit-friendly; block is the one to expect a warning on.
FOUT still happens even with preload, just shorter
By designPreloading does not eliminate FOUT under swap; it shortens the window between the fallback paint and the swap by starting the fetch earlier. If you want to eliminate the flash entirely on uncached visits you must accept optional (no first-visit web font) — there is no value that gives both instant brand font and zero flash on a cold cache.
The tool explains the flashes but does not measure them
SupportedThis is a generative, text-only tool: it formats an explainer and an @font-face skeleton and recommends a value. It does not profile your page, measure LCP/CLS, or detect which flash you currently ship. Use DevTools throttling or Lighthouse for measurement; use this tool to settle the strategy. The result badge reads 0 bytes uploaded.
Frequently asked questions
What is the difference between FOUT and FOIT?
FOIT (Flash of Invisible Text) hides the text until the web font loads — blank space, then the font. FOUT (Flash of Unstyled Text) shows a fallback font immediately and then swaps to the web font when it arrives. FOUT lets people read straight away in the wrong font; FOIT makes them wait. Which one you get is set by the font-display descriptor.
Which font-display value gives FOUT and which gives FOIT?
swap gives pure FOUT (fallback immediately, always swap later). block and auto give FOIT (invisible text, up to ~3s). fallback and optional give a brief ~100ms FOIT followed by fallback, with fallback swapping if the font loads within ~3s and optional swapping only if it is near-instant.
Is FOUT or FOIT better?
For real text, FOUT is almost always better: readable text immediately beats blank space, and it helps Largest Contentful Paint. The only common exception is icon fonts, where the fallback glyph is a meaningless box — there a brief FOIT (block) can be the lesser evil. The picker recommends FOUT-producing values (swap/optional) for everything else.
How do I get FOUT instead of FOIT?
Set font-display: swap; on the @font-face rule. That forces the fallback to render immediately (FOUT) instead of hiding the text (FOIT). The picker's Brand-critical and Balanced modes both recommend swap; copy that line into your real @font-face block.
Does FOUT hurt my Core Web Vitals?
It helps LCP and FCP because text paints early, but the swap reflow can add to Cumulative Layout Shift if the fallback and web font have different metrics. The fix is not font-display — it is size-adjust/ascent-override or a metrically-compatible fallback. Net, FOUT is usually better for CWV than FOIT's late paint.
Why does optional sometimes never show my web font?
After a brief ~100ms FOIT, optional renders the fallback and only uses the web font if it is cached or near-instant. On a cold first visit it normally misses that window, so it stays on the fallback for the session and caches the font for next time — meaning no FOUT flash but also no first-visit brand font. Use swap if the font must show on visit one.
Can I avoid both FOUT and FOIT entirely?
Not on an uncached first visit. If the font is not yet downloaded, the browser must either wait (FOIT) or show a fallback (FOUT). optional comes closest to 'no flash' by mostly skipping the web font on first load, but that means the visitor does not see your font at all that session. There is no value that gives instant brand font and zero flash on a cold cache.
When is FOIT actually acceptable?
For icon fonts. A fallback glyph for an icon renders as a tofu box or a wrong character, which is worse than nothing for a beat. There, block (long FOIT) can be the right call. For prose, headlines, and UI labels, FOIT just delays readable content — use a FOUT-producing value instead.
Does preloading remove the flash?
It shortens the FOUT window under swap by starting the font fetch before the CSS is parsed, so the swap happens sooner and is less noticeable. It does not eliminate FOUT — the fallback still paints first. Generate a preload tag with the preload tag builder and place it in <head>.
Why does my font flash differently in Safari than in Chrome?
You are probably shipping auto, which resolves to the engine default and is not consistent across browsers. Replace it with an explicit value (swap, fallback, or optional) and the flash becomes identical everywhere. This is the most common cross-browser font-loading inconsistency.
Does this tool show me which flash my site currently has?
No — it is a generative explainer and value recommender. It does not profile your page or detect your current font-display. Use DevTools Network throttling and Lighthouse's font-display audit to observe the live flash, and use this tool to decide which value to ship.
How do I make the FOUT swap less jarring?
Match the fallback to the web font so the swap moves the layout less: pick a fallback with a similar x-height and advance width, or add size-adjust, ascent-override, and descent-override to the @font-face. font-display controls whether the swap happens, not how big the resulting shift is — that is the metrics' job.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.