In this post I’ll show you how you can easily add Google Fonts or your own custom fonts to a block theme and how you can customize the generated @font-face rules if needed.
Font loading basics
If you’re adding a font to any webpage (WordPress or otherwise) there are a few things you need to do:
- Upload the font files somewhere publicly accessible on the internet (usually on the same server/hosting)
- Add an
@font-facerule to a stylesheet - Add at least one style that uses the font-family you’ve added1
- Add that stylesheet with the font-styles and @font-face rule to the page.
Adding a @font-face rule is pretty straightforward but it has a few different parts that you need to get right:
@font-face {
font-family: "Bazinga";
src:
local("Bazinga"),
url("./path-to-font/bazinga-regular.woff2") format("woff2");
}CSSIn the above example, we’re loading a font-family called “Bazinga”. The src declaration tells the browser where to find the files for this font. The example uses the local function to tell the browser to look for a font installed on the user’s device that matches the provided name (Bazinga) and provides a woff2 version if they don’t have it installed.
If you’ve been writing CSS awhile, you may be used to loading several different font files for a single @font-face rule (like otf, woff, woff2, etc). This was previously done because not all browsers supported modern webfont file formats (such as woff and later woff2) but in 2025 this is largely unnecessary2.
If you’re loading multiple weights for a font (such as bold, semibold, narrow, black, etc) then you need an additional @font-face rule for each. Variable fonts are the exception here but even variable fonts are sometimes split into 2 versions (ex: italic and non-italic). So the exact implementation largely depends on what font (and what weights) you’re deciding to use.
If you’re using a hosted font service like Google Fonts, Typography.com, Adobe Fonts, or similar services, these services take care of the @font-face rule and hosting the font files for you. All you need to do is add that stylesheet to your page(s) and then make sure your own styles use the font-family in question. If you’re using the same font for the whole site, this might just be a style that targets the body tag like this:
body {
font-family: 'Bazinga', sans-serif;
}CSSWhile straightforward, there’s a lot of different things you need to do. And even if you’re experienced it can be easy to miss a step and it can take some time to do. Furthermore, if you’re not a CSS or webfont expert, doing your own @font-face rule might feel daunting at first.
Furthermore, for optimal performance and privacy 3you should host the font-files on your own website anyway. But doing so does involve a bit more legwork as we just established.
Thankfully the Site Editor makes this a lot easier to do while still giving you a large degree of control over your fonts!
Enter global typography styles
The Site Editor has a concept for Global Styles, which as the name suggests are styles that apply globally (i.e. everywhere) on your site. Part of these settings include typography settings which allow you to specify typography settings for various elements as well as determine which fonts your site uses.

When you upload font files, the Font Library will parse the file to read information about the font and then display it in a list. Here’s an example of the Hellix font that I use on this site:

Each font family you designate has its own font variants. All of the variants for each font-family are output in a style tag with the id “wp-fonts-local”. You can inspect the raw output in the source of this post, but here’s what it looks like (with formatting for legibility):
<style id="wp-fonts-local">
@font-face {
font-family: Hellix;
font-style: normal;
font-weight: 900;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-Black.woff2')
format('woff2');
}
@font-face {
font-family: Hellix;
font-style: italic;
font-weight: 900;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-BlackItalic.woff2')
format('woff2');
}
@font-face {
font-family: Hellix;
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-Bold.woff2')
format('woff2');
}
@font-face {
font-family: Hellix;
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-BoldItalic.woff2')
format('woff2');
}
@font-face {
font-family: Hellix;
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-Regular.woff2')
format('woff2');
}
@font-face {
font-family: Hellix;
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url('https://www.learnwptheme.dev/wp-content/uploads/fonts/Hellix-RegularItalic.woff2')
format('woff2');
}
</style>HTMLOnce you’ve uploaded some font variants , you can then choose it from the Font Family dropdown when you’re setting global typography styles or when you’re styling individual blocks. If any blocks or other elements are using a font, the browser will download the font for use at the indicated URL(s).

If you don’t want to customize the font-face declaration in some way, this is all you have to do! You don’t actually have to write any custom CSS or add a stylesheet to achieve the above.
But wait, you say. What if I want to customize the font-face declaration? What if I want to do things like add font-display (which is important for Core Web Vitals)? Worry not friend, for you can still customize these font-face declarations using theme.json if need to set any values directly. This gives you the best of both worlds: you can administrate things easily in the site editor while still having control over the resulting styles!
In order to customize the @font-face declaration, you’ll need to edit your theme.json file. This allows you to set additional values that are currently not available in the Site Editor UI. The easiest way to do this is to use Create Block Theme to save the changes for your theme to the theme folder itself.
Saving the font families to theme.json with Create Block Theme
The plugin description for Create Block Theme describes it as “Development Mode for WordPress” which is a handy way to think about how this plugin works. Create Block Theme provides additional options for the Site Editor that developers care about, such as the ability to keep changes to the theme version controlled in theme files.
While you may not care to do this with everything (or even every time you make template changes) you’ll need to do this at least once in order to customize the font-face declaration.
To get started, you’ll need to download and activate the Create Block Theme plugin from the WordPress Plugin directory. Once you do this, if you enter the Site Editor and go to edit a template, there will be a new wrench icon that opens up a settings panel for Create Block Theme.

If you click “Save Changes to Theme” you’ll see another menu that gives you a few options of what things you want to save.

Note:
Be very careful about what boxes you leave checked here. While many of these are pretty safe, they do make changes to your theme’s files. For instance, “Save Fonts” will save the font families you’ve specified to theme.json, but it will also remove any fonts you have deactivated (unchecked) in the Font Library.
Make sure you read the description of what each check does before leaving it selected.
When you first upload fonts to your WordPress site, those font files are stored in the uploads folder. When you run “Save Changes” with “Save Fonts” checked, those font files are relocated to your theme’s assets/fonts folder and then the font-family details are saved to your theme’s theme.json file.
Once you’ve saved, the Site Editor will reload and your theme’s files will be updated. If you want to see the changes to theme.json, you can use the “View theme.json” button in the Create Block Theme settings panel or inspect the file in your theme folder directly using SFTP or a similar method:

To actually modify theme.json, you’ll need to edit the file directly. For best results, I’d recommend using a code editor such as VS Code, Cursor, or similar to do this. Many editors have support for JSON Schema built in, which tells you what keys are able to be used in the various parts of the theme.json file. This is a big help especially if you don’t remember all of them by part (like most of us!).
Customizing the @font-face declarations
Let’s say that you want to set font-display: swap; for each of the @font-face rules. You’d just need to add a new key (fontDisplay) to the object for the associated font-face rule. Let’s take a look at the theme.json contents for settings.typography.fontFamilies a bit closer. Each font-family we set up in the Font Library earlier is accounted for here. Each font-family will also have a fontFace array (with the exception of the system fonts because by definition we aren’t loading any files for that family).4
In the below snippet, you can see the value of the fontFace key for the Hellix font. Since I uploaded those files through the Font Library originally, WordPress is generating the @font-face rule for me.
"typography": {
"fluid": true,
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
"name": "System Fonts",
"slug": "system"
},
{
"fontFace": [
{
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "900",
"src": [
"file:./assets/fonts/hellix/hellix-900-normal.woff2"
]
},
{
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "900",
"src": [
"file:./assets/fonts/hellix/hellix-900-italic.woff2"
]
},
{
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "700",
"src": [
"file:./assets/fonts/hellix/hellix-700-normal.woff2"
]
},
{
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "700",
"src": [
"file:./assets/fonts/hellix/hellix-700-italic.woff2"
]
},
{
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "400",
"src": [
"file:./assets/fonts/hellix/hellix-400-normal.woff2"
]
},
{
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "400",
"src": [
"file:./assets/fonts/hellix/hellix-400-italic.woff2"
]
}
],
"fontFamily": "Hellix",
"name": "Hellix",
"slug": "hellix"
}
],
...
}JSONSo if I wanted to add font-display: swap; to each font variant for Hellix, I just need to add a fontDisplay key inside each object in the fontFace array and set the value to swap. Once this is added, the generated @font-face output will now include font-display: swap5.
{
"fontFace": [
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "900",
"src": [
"file:./assets/fonts/hellix/hellix-900-normal.woff2"
]
},
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "900",
"src": [
"file:./assets/fonts/hellix/hellix-900-italic.woff2"
]
},
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "700",
"src": [
"file:./assets/fonts/hellix/hellix-700-normal.woff2"
]
},
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "700",
"src": [
"file:./assets/fonts/hellix/hellix-700-italic.woff2"
]
},
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "normal",
"fontWeight": "400",
"src": [
"file:./assets/fonts/hellix/hellix-400-normal.woff2"
]
},
{
"fontDisplay": "swap",
"fontFamily": "Hellix",
"fontStyle": "italic",
"fontWeight": "400",
"src": [
"file:./assets/fonts/hellix/hellix-400-italic.woff2"
]
}
],
"fontFamily": "Hellix",
"name": "Hellix",
"slug": "hellix"
}JSONOther @font-face rules you can change
Beyond font-display, there are a number of other properties you can set here too. Some of these are only relevant to variable fonts, but others allow you to do more advanced things like subsetting fonts using unicode-range.
Here’s a list of the available options as of WordPress 6.8:
- fontDisplay
- fontStretch
- ascentOverride
- descentOverride
- fontVariant
- fontFeatureSettings
- fontVariationSettings
- lineGapOverride
- sizeAdjust
- unicodeRange
You can read more about Typography settings in theme.json in the Theme Developer Handbook.
What about Google Fonts?
The WordPress Font Library also lets you download and use Google Fonts on your site. Once you authorize the Font Library to use Google Fonts, you can search and select any of the available fonts and use them just like a font you upload yourself.

Once you’ve installed a Google Font, the process for customizing @font-face is exactly the same! The files are downloaded to your site just as though you had uploaded them so you’re still self-hosting the fonts. This makes it easy to use Google Fonts in a way that is performant and privacy focused.
More about the Font Library
The announcement post on the Font Library goes over some details about a few other things, including how you can add your own font collections. This is a more advanced use case but it’s pretty cool stuff and especially relevant if you’re attempting to extend the font library in some way.
I’d encourage you to read the post on make.wordpress.org if you’re interested in more technical details!
Conclusion
The Font Library is a really handy feature that you can use to save yourself time and make it easy for low/no-code users and other developers alike to use custom fonts in your block theme. With the power of the Site Editor and theme.json, you can use a nice GUI and still retain control over the resulting CSS.
- If you don’t actually use the font anywhere on the page, the browser will not download it. This is great because it ensures you’re not loading up a bunch of fonts that aren’t being used and slowing the page down! ↩︎
- Fallbacks aren’t necessary anymore because virtually every major browser has supported WOFF2 (the most optimized webfont format) since 2018. If you know for sure that your website audience is using an ancient browser version then you may still need to do this (but you probably don’t). WOFF2 files are a compressed version of WOFF files and will load the fastest/best on modern devices. WOFF files themselves have even wider support and if that’s the only version you have for your font that will work fine also. Older formats like TTF, OTF, and EOT shouldn’t be used anymore. ↩︎
- If your site is subject to GDPR regulations, you probably need to host the fonts yourself. Even then, hosting the fonts on your own server will load faster than loading them from another origin (i.e. another domain). If you’re interested in the technical details behind this, check out this great deep-dive from the venerable Harry Roberts (link). ↩︎
- Any font-family you may have written into theme.json but didn’t upload via the Font Library before will not have an @font-face declaration generated for it. This is most common when you write in your own @font-face declaration in a stylesheet and then just add the preset in here so it appears as a choice in the editor. ↩︎
- By default WordPress will use a font-display value of fallback if you don’t set one yourself. ↩︎