Top Rated on Upwork Before-and-after PageSpeed report included Replies within 1 hour Get a free speed audit →
Frontend

WordPress Fonts: Optimize Them So They Stop Slowing Your Pages

WordPress fonts are the web fonts your theme and plugins load, and they slow pages when they render-block, ship extra weights, or shift layout. You fix them by hosting fonts locally, limiting weights, setting font-display: swap, and preloading only the critical above-fold font.

By Maryam, WordPress Speed Optimization Expert Updated June 2026 3+ years on WordPress speed
wordpress fontsoptimize fonts wordpressfont-display swap wordpresshost google fonts locallywordpress web fonts performancepreload font wordpresswoff2 wordpresssystem font stack
3D illustration of a polished chrome capital-letter glyph sculpture beside a browser with a green
Direct answer

WordPress fonts are the web fonts your theme and plugins load, and they slow pages when they render-block, ship extra weights, or shift layout. You fix them by hosting fonts locally, limiting weights, setting font-display: swap, and preloading only the critical above-fold font. If I were checking this on a real site, I'd start with the page that earns traffic or money, confirm whether the issue is backend, frontend, content, or layout related, then apply one fix at a time.

What are WordPress fonts and why do they hurt speed?

WordPress fonts are the web fonts your theme, page builder, and plugins load to render text, and they hurt speed when each one arrives as a separate render-blocking request, ships weights you never use, or swaps in late and shoves your layout around. A single typeface family pulling four weights from a third party can add three to six extra requests plus a fresh DNS lookup to fonts.gstatic.com, and the browser often hides your text until those files land.

I've audited hundreds of WordPress sites, and fonts are almost always in the top three render-blocking offenders behind CSS and JavaScript. They're sneaky because the file sizes look small, 20 to 40 KB per weight in WOFF2, so people ignore them. The damage isn't the bytes. It's the connection setup to a third-party host, the render-blocking position in the <head>, and the layout shift when a fallback font gets replaced. Get those three things right and fonts cost you almost nothing.

If your PageSpeed report flags "Ensure text remains visible during webfont load" or "Preconnect to required origins," that's a font problem, and it's worth fixing alongside the rest of your WordPress speed optimization work. Fonts touch three Core Web Vitals at once: LCP if your headline text waits on a font, CLS if the swap reflows the page, and a bit of TBT from the extra blocking work.

How do I audit which fonts my WordPress site loads?

You audit your fonts by opening Chrome DevTools, going to the Network tab, filtering by "Font," and reloading the page so you can see every font file, its size, its host, and whether it blocked rendering. This takes about two minutes and it's the step most people skip, so they end up optimizing fonts they don't even use.

Here's the workflow I run on every site:

  1. Open DevTools, Network tab, type font in the filter, hard-reload.
  2. Count the files. More than two or three usually means a plugin or builder is loading its own duplicate set.
  3. Check the Domain column. Anything from fonts.gstatic.com or fonts.googleapis.com is a third-party request you can eliminate by self-hosting.
  4. Look at the Initiator and the weights. If you see 300, 400, 600, and 700 but your design only uses regular and bold, you're shipping two dead files on every load.
  5. Run the page through PageSpeed Insights and read the "Reduce unused CSS" and "Eliminate render-blocking resources" items, since builder font CSS shows up there too.

I also keep Query Monitor installed while I work, because it shows which plugin or theme enqueued each stylesheet, so I can trace a mystery font back to its source. If the audit feels overwhelming on a big site, our free WordPress audit will flag the font issues for you with the exact files named.

Should I host Google Fonts locally in WordPress?

Yes, you should host Google Fonts locally in almost every case, because serving the WOFF2 files from your own domain removes a third-party DNS lookup and connection handshake, lets the browser cache them on the same origin, and keeps you GDPR-clean since no visitor IP gets sent to Google. Self-hosting is the single highest-impact font fix I make, and it's usually a five-minute job.

The reason it's faster comes down to the connection cost. When fonts live on fonts.gstatic.com, the browser has to do a DNS lookup, a TCP handshake, and a TLS negotiation to a brand-new host before it can even start downloading a single byte. That setup can burn 100 to 300 ms on a mobile connection. When the font sits on your own domain, that connection's already open from loading the HTML, so the file starts downloading right away.

The easy way is the OMGF plugin. It scans your pages, finds every Google Font, downloads the WOFF2 files to your server, rewrites the CSS to point at the local copies, and removes the calls to Google. Install it, hit "Save & Optimize," and it does the swap. If you'd rather go manual, download the WOFF2 files, drop them in a /fonts/ folder in your child theme, and write your own @font-face rules pointing at them. Page builders complicate this, and I cover that in why Elementor loads slowly, since Elementor and Divi both bundle their own Google Fonts loaders you have to switch off.

What does font-display: swap do and should I use it?

The font-display: swap rule tells the browser to show your text immediately in a fallback system font, then swap in your custom font once it's loaded, which kills the Flash of Invisible Text that hides your content while a font downloads. You should use it on body text everywhere, because invisible text during load tanks both LCP and the real reading experience.

Without a font-display value, browsers default to a roughly three-second block period where your text is invisible. On a slow connection your visitor stares at a blank page while the font crawls in. That blank period is exactly what PageSpeed flags as "Ensure text remains visible during webfont load." Adding swap to every @font-face rule fixes it.

There are four values and they matter:

  • swap: fallback shows instantly, custom font swaps in whenever it arrives. Best default for body text.
  • optional: fallback shows, and the custom font only swaps in if it's already cached. This one eliminates layout shift entirely because there's no late swap, which makes it my pick for sites where CLS is the bigger problem.
  • block: short invisible period then swap. Avoid it, it reintroduces FOIT.
  • fallback: tiny block, then a short swap window, then it gives up. A middle ground I rarely reach for.

OMGF, WP Rocket, and LiteSpeed Cache all let you force swap across every stylesheet with one toggle, so you don't have to hand-edit CSS. If you self-host manually, just add font-display: swap; inside each @font-face block.

How many font weights and subsets should I load?

You should load only the weights and character subsets you actually use on the page, which for most sites means two weights per family (regular and bold) and the Latin subset alone, since every extra weight is a separate file and every unused subset is wasted bytes inside each file. I've seen sites loading seven weights and the full Cyrillic, Greek, and Vietnamese character ranges for an English-only blog. That's the easiest fat to cut.

Here's how I decide. Open the rendered site, look at the actual headings and body copy, and list the weights in use. A typical design needs regular (400) and bold (700), sometimes a semibold (600) for headings. If your design uses a single weight, load one file. Italic only counts if you genuinely use italic text, and most sites fake it with a synthesized slant they never asked for.

Subsetting trims the unused characters out of each file. A full Google Font WOFF2 carries Latin, Latin-extended, Cyrillic, Greek, and Vietnamese glyphs. An English site needs Latin, full stop. Stripping the rest with a tool like Glyphhanger or Transfonter can shave 30 to 60 percent off each file. OMGF lets you pick subsets in its settings, and most cache plugins expose a weight selector too. Cutting from five weights to two across two families is often the difference between six font requests and two, which feeds straight into the render-blocking resources you're trying to clear.

How do I preload the right font without slowing the page?

You preload a font by adding a <link rel="preload" as="font" type="font/woff2" crossorigin> tag in the <head> for the one or two fonts your above-the-fold text needs, and the trick is to preload only those critical files, never your whole font set. Preloading tells the browser to grab the font early instead of waiting to discover it inside a CSS file, which shortens the swap delay and helps your LCP element render in its final font sooner.

Here's the decision rule I follow, because this is where most people go wrong: preload the font that renders your largest above-the-fold text and nothing else. If your hero headline uses your bold weight and your body uses regular, preload both of those WOFF2 files and stop there. Preloading every weight does the opposite of what you want, it competes with your CSS and images for early bandwidth and pushes back the very LCP element you were trying to speed up.

The crossorigin attribute is mandatory on font preloads even for same-origin files, because fonts are always fetched in CORS mode, and leaving it off makes the browser download the file twice. WP Rocket has a "Preload Fonts" field where you paste the file URLs, LiteSpeed Cache has the same under its tuning options, and OMGF Pro can flag fonts to preload automatically. I go deeper on the mechanics in the preconnect and preload guide, since the same rules apply to other critical assets.

Do web fonts cause layout shift, and how do I stop it?

Yes, web fonts cause layout shift when the fallback font and your custom font have different dimensions, so when the swap happens the text block changes height or width and pushes everything below it down the page, which registers as Cumulative Layout Shift. This is the font problem people miss, because they fix the invisible-text issue with swap and accidentally trade it for a CLS hit.

The cleanest fix is to match the fallback metrics to your custom font using CSS descriptors. You declare a fallback @font-face with size-adjust, ascent-override, descent-override, and line-gap-override tuned so the system font occupies the same space your real font will. When the swap fires, nothing moves, because both fonts take up identical room. Chrome and Firefox both honor these descriptors now, and they're the modern answer to font-driven CLS.

If hand-tuning metrics feels heavy, two simpler moves help a lot: use font-display: optional so the custom font only swaps when it's already cached (no late reflow), and pick a fallback in your stack that's close in width to your custom font. I cover the full reflow story in fixing cumulative layout shift in WordPress, because fonts are one of three big CLS sources along with images and ads. You can confirm the shift is gone by recording a performance trace in DevTools and watching for layout-shift entries during font load.

Should I just use system fonts instead?

You should use a system font stack when brand typography isn't critical, because system fonts ship with the visitor's device, load instantly with zero network requests, and produce zero layout shift, which makes them the fastest possible choice for performance-first sites. The tradeoff is you give up a custom typeface, so this is a judgment call, not a universal rule.

A system font stack looks like font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;. The browser picks whichever native UI font the device already has, so a Mac shows San Francisco, Windows shows Segoe UI, Android shows Roboto, and none of them costs a single download. That's why GitHub, WordPress admin, and a lot of speed-obsessed sites run on system fonts.

My honest take after years of this work: if a client's brand lives and dies on a specific typeface, I keep it and optimize it properly. But for a fast blog, a documentation site, or anything where readability beats brand personality, I'll push system fonts hard because they remove an entire category of performance problems. You can also use a hybrid, system fonts for body text and one custom font for headings only, which keeps the heavy lifting on just a couple of files.

Which plugin handles WordPress font optimization best?

For dedicated font handling, OMGF is the best free option because it self-hosts Google Fonts, forces font-display, and manages subsets and preloads in one place, while WP Rocket and LiteSpeed Cache fold font optimization into their broader caching suites so you don't run a separate plugin. The right pick depends on whether you already run a cache plugin.

Here's how I choose:

  • OMGF: the specialist. If your only goal is fixing Google Fonts, install OMGF, let it localize everything, force swap, and trim subsets. Free version covers most sites.
  • WP Rocket: if you already use it for caching, turn on "Optimize Google Fonts" plus its preload-fonts field and you're done in one dashboard. See my WP Rocket vs LiteSpeed comparison for the full breakdown.
  • LiteSpeed Cache: free and powerful if you're on LiteSpeed hosting. It localizes Google Fonts, forces font-display, and handles preload under its page-optimization tab.
  • Perfmatters: pairs well with any of the above to disable the font loaders that themes and builders inject.

Don't stack two plugins both trying to optimize the same fonts, because they'll fight and you'll get double-loaded files or broken CSS. Pick one font owner. If OMGF handles fonts, tell WP Rocket to leave them alone, and vice versa.

What are the most common WordPress font mistakes?

The most common WordPress font mistakes are loading weights you never use, leaving fonts on a render-blocking third-party request, and preloading every font instead of just the critical one, and each of these is something I fix on nearly every site I audit. They're easy to make because page builders and themes do them for you by default.

The big ones, in order of how often I see them:

  • Shipping unused weights. Five weights load, the design uses two. Three wasted files on every page view.
  • Third-party render-blocking requests. Fonts still calling fonts.gstatic.com, adding a DNS lookup and a connection handshake before any text renders.
  • Preloading everything. Preload tags on six font files, which floods early bandwidth and slows the LCP element you wanted to speed up.
  • Forgetting crossorigin on preloads. The font downloads twice, doubling its cost.
  • Fixing FOIT but creating CLS. Adding swap without matching fallback metrics, so the page reflows when the font lands.
  • Letting two plugins manage fonts at once. Conflicting rules, double-loaded files, broken @font-face.
  • Loading icon fonts for two icons. A whole Font Awesome file for a couple of glyphs you could ship as inline SVG.

If you've been chasing your LCP score, fonts are often the hidden cause, and the LCP optimization guide ties the font fixes back to the metric.

When should you hire someone for font and speed work?

You should hire help when font fixes don't move your scores, when a page builder keeps re-injecting fonts you've removed, or when you've got real revenue riding on Core Web Vitals and can't afford trial and error, because at that point the time you'd spend chasing it costs more than the fix. Font optimization is simple in theory and fiddly in practice once builders, caching, and CDNs all interact.

I'll be honest about where DIY runs out. Self-hosting fonts and forcing swap are genuinely easy, anyone can do those with OMGF in ten minutes. The hard part is the last mile: tuning fallback metrics to zero out CLS, untangling why Elementor keeps loading a font you killed, or getting Cloudflare to cache your local fonts correctly. That's where most people lose a weekend.

If you'd rather hand it off, that's what I do for a living. My WordPress speed optimization service covers fonts as part of a full Core Web Vitals pass, so the fonts get fixed in context with your CSS, images, and caching instead of in isolation. Either way, start with the audit, fix the obvious weight and self-hosting wins yourself, and bring in help only for the parts that fight back.

My checklist for WordPress Font Optimization

how many font files and weights load

whether Google Fonts load from a third party

whether font-display swap is set

What do people ask about WordPress Font Optimization?

Is it faster to host Google Fonts locally or use Google's CDN? +
Hosting locally is faster for almost every WordPress site. Serving WOFF2 files from your own domain removes a separate DNS lookup and connection handshake to fonts.gstatic.com, and it lets the browser reuse the connection that's already open from loading your HTML. It also keeps you GDPR-compliant since no visitor IP gets sent to Google.
What's the difference between font-display swap and optional? +
Both show a fallback font right away to avoid invisible text. With swap, the browser replaces the fallback with your custom font whenever it finishes loading, which can cause a small layout shift. With optional, it only swaps if the font's already cached, so there's no late reflow. Use optional when CLS is your bigger worry, swap when reading experience matters most.
How many fonts and weights should a WordPress site load? +
Aim for two font families at most, and two weights per family, usually regular and bold. Every extra weight is a separate file the browser has to download. If your design only uses one weight, load one file. Most sites can drop from five or six weights down to two or three without any visible change.
Why does PageSpeed say 'Ensure text remains visible during webfont load'? +
That warning means at least one font is missing a font-display value, so the browser hides the text for up to three seconds while the font loads. Add font-display: swap to every @font-face rule, or let OMGF, WP Rocket, or LiteSpeed Cache force it across all your stylesheets with one setting.
Do I still need to preload fonts if I host them locally? +
Often yes, for the one or two fonts that render your above-the-fold text. Self-hosting removes the third-party connection cost, but preloading tells the browser to fetch the critical font early instead of discovering it inside a CSS file. Preload only the above-fold fonts, never your whole set, and always include the crossorigin attribute.
Can web fonts hurt my Cumulative Layout Shift score? +
Yes. When your fallback font and custom font have different dimensions, the text block changes size during the swap and pushes content down, which CLS measures. Fix it by matching fallback metrics with size-adjust and the ascent, descent, and line-gap override descriptors, or by using font-display: optional to avoid the late swap entirely.
Are system fonts a good alternative for WordPress? +
They're the fastest option since they ship with the visitor's device, load with zero requests, and cause zero layout shift. The tradeoff is you lose custom branding. A good compromise is using a system font stack for body text and one custom font for headings only, which keeps the network cost to a couple of files.