Skip to content

Google Fonts (Beta) module disables core wp_print_font_faces() and drops/overrides theme.json fonts on the front end #50180

Description

@iamtakashi

Impacted plugin

Jetpack

Quick summary

The Google Fonts module is deprecated (WP 6.5+ supports fonts natively) but still ships and, wherever it's active, removes core's native font-face printing and substitutes its own "in-use only" printer. This causes two front-end regressions for themes that register a font via theme.json:

  1. The font disappears if the font-family usage value includes a fallback stack (var(--wp--preset--font-family--slug), system-ui, …) instead of a bare var(...) — the in-use scan misses it and prints nothing for that family.
  2. Even when it "works," the wrong font paints — the module injects its own fonts.wp.com copy of the same-named family alongside the theme's bundled file: faces, so visitors get Google's hosted version instead of the file the theme ships.

Both render fine in the Site Editor; only the front end is affected, and no warning is emitted.

Steps to reproduce

  1. Block theme registers a font in theme.json with a bundled fontFace (src: ["file:./…/InterVariable.woff2"], slug inter).
  2. Reference it in styles with a fallback stack:
"styles": { 
   "typography": {
      "fontFamily": "var(--wp--preset--font-family--inter), system-ui, sans-serif"
    }
}
  1. Enable the Google Fonts module; view the front end (logged out / cache bypassed)

Expected: the @font-face prints and the bundled font loads (as core wp_print_font_faces() does when the module is off).
Actual: no @font-face prints for that family; it falls back to a system font.

Site owner impact

More than 60% of the total website/platform users

Severity

Moderate

What other impact(s) does this issue have?

No response

If a workaround is available, please outline it here.

A) Toggle the module, holding theme.json constant (compound usage as above). Isolates the module as the cause:

Google Fonts module Front-end result
ON 0 @font-face, no wp-fonts-local, font gone → system fallback Image
OFF core wp-fonts-local prints the theme's InterVariable faces, font restored Image

Same theme, same theme.json — the font's presence tracks the module exactly.

B) Hold the module ON, vary only the usage value. Isolates the compound-value trigger:

styles…fontFamily usage Front-end @font-face
var(--wp--preset--font-family--inter) (bare) 11 (9 fonts.wp.com + 2 theme faces) — works
var(--wp--preset--font-family--inter), system-ui, … (compound) 0 — system fallback

C) Font substitution (bare usage, so the font is present; toggle only the module). Even when it "works," the module changes which font paints:

Module Face that paints "Handgloves wwiill 12345" @ 60px / wt 300
OFF theme's bundled InterVariable.woff2 ~623px
ON Jetpack fonts.wp.com Inter (v13 static) ~691px
On Off
Image Image

Root cause

Jetpack_Google_Font_Face (projects/plugins/jetpack/modules/google-fonts/current/class-jetpack-google-font-face.php) removes core/Gutenberg printing on wp_loaded:

remove_action( 'wp_head', 'wp_print_font_faces', 50 );
remove_action( 'wp_head', 'gutenberg_print_font_faces', 50 );

then prints only fonts detected in use. Slug detection is anchored to a trailing ):

// get_font_slug_from_setting()
preg_match( '/font-family--(?P<slug>.+)\)$/', $font_family, $matches );

A compound value doesn't end in ), so detection fails, the family isn't in $fonts_in_use, and — with core's printer already removed — nothing prints for it. Separately, print_font_faces() emits the module's fonts.wp.com faces for detected families even when the theme already registers that family with a local file: source, so the hosted copy wins over the bundled file.

Suggested fix

Since the module is deprecated in favor of native WP fonts, it should not remove core wp_print_font_faces() on WP ≥ 6.5 — defer to native, or auto-skip when native font support is present. At minimum:

  • Make in-use detection tolerant of compound values — parse the leading var(--wp--preset--font-family--<slug>) token instead of anchoring to )$ (e.g. drop $ / split on ,).
  • Fall through to core for theme-registered file: faces the module doesn't manage, so a detection miss degrades gracefully instead of dropping a shipped font.
  • Don't inject a fonts.wp.com copy for a family the theme already registers with a local file: source.

I noticed this while I'm working on a theme in an Atomic site. Claude help me to write this.

Platform (Simple and/or Atomic)

Simple, Atomic, Self-hosted

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugWhen a feature is broken and / or not performing as intendedNeeds triageTicket needs to be triaged

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions