Adding Custom Fonts to the WordPress Site Editor UI

Registering custom fonts in WordPress has typically been a straightforward thing when theming. Do it in the CSS a la @font-face and style away!

@font-face {
  font-family: "My Custom Font";
  src: url("path/to-font-file.woff2");
}

But now with full-site editing in the wild as of WordPress 5.9, you might want to give yourself or your clients. That’s where the WordPress Webfonts API will come in handy. I say ”will” because it ain’t here just yet. It was originally slated to release in WordPress 5.9 but has actually been moved to the Gutenberg plugin for the time being. The Make WordPress Core blog provides nice context as far as where that work is happening, as well as examples of how it could work.

TL;DR: There are two ways to register a custom font.

The theme.json way

This is the future-friendly way of going about it once the WordPress Webfonts API officially makes its way in to Core. We can register and define a font in a theme.json file the same way we can register and define things like color.

The API ordering goes:

  • settings
    • typography
      • fontFamilies
        • fontFamily
        • slug
        • name
        • fontFace
          • fontFamily
          • fontWeight
          • fontStyle
          • src

If you’re already familiar with the CSS @font-face syntax, you’ll recognize all those properties since it’s all one-to-one. Here’s a slightly modified example pulled straight from the GitHub ticket for the patch that was merged into Gutenberg.

First, define the fonts in theme.json:

"fontFamilies": [
  {
    "fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
    "name": "Display Font",
    "slug": "system-font"
  },
  {
    "fontFamily": "\"Source Serif Pro\", serif",
    "name": "Body Font",
    "slug": "source-serif-pero",
    "fontFace": [
      {
	"fontFamily": "Source Serif Pro",
	"fontWeight": "200 900",
	"fontStyle": "normal",
	"fontStretch": "normal",
	"src": [ "file:./assets/fonts/SourceSerif4Variable-Roman.ttf.woff2" ]
      },
      {
        "fontFamily": "Source Serif Pro",
        "fontWeight": "200 900",
        "fontStyle": "italic",
        "fontStretch": "normal",
        "src": [ "file:./assets/fonts/SourceSerif4Variable-Italic.ttf.woff2" ]
      }
    ]
  }
],

The PHP way

It just wouldn’t be WordPress without a PHP alternative for those working in classic themes. Again, slightly modified from the ticket showing the wp_register_webfonts() function in use:

add_action( 'after_setup_theme', function() {
  if ( ! function_exists( 'wp_register_webfonts' ) ) {
    return;
  }
  wp_register_webfonts(
    array(
      array(
        'font-family'  => 'Heading Font',
        'font-weight'  => '200 900',
        'font-style'   => 'normal',
        'font-stretch' => 'normal',
        'src'          => array( 'file:./assets/fonts/SourceSerif4Variable-Roman.ttf.woff2' ),
      ),
      array(
        'font-family'  => 'Body Font',
        'font-weight'  => '200 900',
        'font-style'   => 'italic',
        'font-stretch' => 'normal',
        'src'          => array( 'file:./assets/fonts/SourceSerif4Variable-Italic.ttf.woff2' ),
      ),
    )
  );
});

Use them in the editor

I named the two registered fonts “Heading Font” and “Body Font” to distinguish them from one another by their intended use. But you could just as easily use the actual font name since name property takes any string.

Showing the registered fonts in the Site Editor interface.

Um, Google Fonts?

Not yet. The Gutenberg patch is only good for local fonts at the moment. The Google Fonts provider was pulled from the Gutenberg project late last year. I imagine it’s coming and we’ll be able to chuck a Google Fonts URL in the src property or perhaps have some new provider property at some point. ????‍♂️

The issue apparently is that there’s currently no way to hook into global styles as of WordPress 5.9. And the issue seems to be with the theme.json method.

Justin Tadlock did some digging and found that Automattic already has its own patch drafted for this in Jetpack.

In the meantime, it’s still possible to enqueue a Google Font:

add_action( 'wp_enqueue_scripts', function() {
  wp_enqueue_webfont(
    // Handle
    'smooch-sans',
    // CSS URL
    'https://fonts.googleapis.com/css2?family=Biryani:wght@800&family=Megrim&family=Smooch+Sans&display=swap', 
  );
});

That’s great and all, but basically only makes the webfont available to use in CSS. In other words, there’s no impact to the editing UI.

Another option? Download the font file from Google Fonts, serve it locally, then theme.json it.

✏️ Handwritten by Geoff Graham on March 4, 2022

13 Comments

  1. Sam
    # March 16, 2022

    Does “‘font-weight’ => ‘200 900′” specify the range of font-weight from 200 TO 900 or does it specify only two weights, 200 AND 900.

    Thanks for the article, Sam

    • # March 18, 2022

      It only defines which weights to use — 200 and 900 in this case.

  2. # May 3, 2022

    Have you come across a way of solving this when using a non-variable font, such as Roboto, where you want to have multiple weights used?

    For example, with this setup only the 400 weight is used for the @font-face declaration while the 700 is ignored altogether.

    {
    "name": "Roboto",
    "slug": "roboto",
    "fontFamily": "\"Roboto\", sans-serif",
    "fontFace": [
    {
    "fontFamily": "Roboto",
    "fontWeight": "400",
    "fontStyle": "normal",
    "src": ["file:./assets/fonts/roboto-v29-latin-regular.woff2"]
    },
    {
    "fontFamily": "Roboto",
    "fontWeight": "700",
    "fontStyle": "normal",
    "src": ["file:./assets/fonts/roboto-v29-latin-700.woff2"]
    }
    ]
    },

    • # May 3, 2022

      Have you tried a different fontFamily name? I suspect that using Roboto for both might cause a conflict. So, perhaps something like Roboto Regular and Roboto Bold?

  3. # October 5, 2022

    When you add the font via theme.json, what happens when the theme is updated, do we lose the custom font changes? Do we need to create a child theme?

    • Geoff Graham
      # October 5, 2022

      If you’re rolling with a third-party theme (including default WP themes), then I’d say a child theme is your best bet. The child theme will basically be a container for your overrides.

  4. # October 11, 2023

    Hi Geoff,

    I want to introduce you to my own solution to add custom font to Gutenberg. Its called “Yabe Webfont” and available on WP repository

Comments are closed.