Theme.json typography: Font family

In this lesson, you will learn how to use theme.json to add font families to your WordPress theme and how to assign different font families to different blocks.

You add font families to theme.json in settings.typography.fontFamilies. You can refer to an existing font family, like a system font, or you can use advanced optional parameters, such as a font face declaration.

When you want to use a custom web font, you no longer need to enqueue it yourself; instead, you can use the src parameter to add a link to the file. WordPress will enqueue the font file for you in both the editors and the front of the site. This makes managing fonts much easier than before. You can also use the new Font Library to preview and download Google Fonts.

I have split the font family and font size lesson into two. You will find information about adding font sizes in theme.json here.

Prerequisites: Global Styles & theme.json.

Last updated

This lesson has been updated for WordPress 6.5.

Estimated reading time: 8 minutes

Which blocks support font family?

You can set a default font family for the site and any text-based block using the theme.json styles section. To find out which blocks have a font family control in the block editor and site editor, you can use the block reference: Block reference: Typography block support.

Once you have registered a font family, it is available in the Font family control in the block’s typography panel:

The block editor Typography panel 
has a font family option with a select list with font family names.

How to add font families using theme.json

There are several ways to reference a font family in theme.json, You can use system fonts, let WordPress enqueue the font files, or enqueue your font files manually. In this lesson I will not explain how to enqueue the files manually.

Basics

Lets start with the basics: You add font families in theme.json by listing them inside the typography section under the main settings section:

settings.typography.fontFamilies

Typography options on the root level of the settings section create presets that you can use for the site, blocks, and theme.json elements.

Note that the category name for the list is fontFamilies (plural). Inside this category, you place the font family names in an array using the following key and value pairs:

  • fontFamily: The font family names (the CSS value).
  • slug: The unique identifier that WordPress uses in the CSS custom property.
  • name: The visible name in the editor (optional).

fontFamily can include one font or several, including your fallback font.

{
	"version": 2,
	"settings": {
		"typography": {
			"fontFamilies": [
				{
					"fontFamily": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif",
					"slug": "system-fonts",
					"name": "System fonts"
				}
			]
		}
	}
}

The resulting CSS custom properties have the following format:

--wp--preset--font-family--slug: fontFamily value
body {
    --wp--preset--font-family--system-fonts: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
}

Using a custom web font

The most common scenario is perhaps to use a combination of web fonts and system fonts. This option also works with variable fonts. To use a web font, for example a font from Google Fonts, you need to download and place the font files in your theme folder. For now, it is assumed that your font files are placed inside an assets/fonts/ folder in your theme.

To reference the font files, you will add an additional setting to fontFamily called fontFace.

This setting represents the @font-face CSS rule. I strongly recommend reading more about @font-face on mdn web docs.

In WordPress 6.5, the fontFace setting received a massive update. These are the most common parameters:

  • fontFamily. The name of the font.
  • src. Source, the path to the file in the theme folder.
  • fontWeight. Optional. A list of available font weights, separated by a space.
  • fontStyle. Optional. Select a font style like normal or italic.
  • fontStretch. Optional. You can for example use this with font families that have a condensed version.

If you want to load two separate font files, for example, one for normal and one for italic, you include them as separate arrays inside fontFace, separated by curly brackets and a comma.

Code example

{
	"version": 2,
	"settings": {
		"typography": {
			"fontFamilies": [
				{
					"fontFamily": "\"Source Serif Pro\", serif",
					"name": "Source Serif Pro",
					"slug": "source-serif-pro",
					"fontFace": [
						{
							"fontFamily": "Source Serif Pro",
							"fontWeight": "400 700",
							"fontStyle": "normal",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/SourceSerifPro-regular.woff2" ]
						},
						{
							"fontFamily": "Source Serif Pro",
							"fontWeight": "400 700",
							"fontStyle": "italic",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/SourceSerifPro-italic.woff2" ]
						}
					]
				}
			]
		}
	}
}

As with the rest of theme.json, font family values are sensitive to typos, this is the most common reason to why your font families don’t work.

All fontFace parameters

Required:

  • fontFamily. The name of the font.
  • src. Source, the path to the file in the theme folder.

Optional:

  • fontWeight, as a list of available font weights, separated by a space.
  • fontStyle. Select a font style like normal or italic.
  • fontStretch. You can for example use this with font families that have a condensed version.
  • fontDisplay. CSS font-display value. One of: auto, block, fallback, swap, optional.
  • ascentOverride. CSS ascent-override value.
  • descentOverride. CSS descent-override value.
  • fontVariant. CSS font-variant value.
  • fontFeatureSettings. CSS font-feature-settings value. It is recommended to use fontVariant instead.
  • fontVariationSettings. CSS font-variation-settings value. Used with variable fonts.
  • lineGapOverride. CSS line-gap-override value.
  • sizeAdjust. CSS size-adjust value.
  • unicodeRange. CSS unicode-range value.

Updated 2024-05-09. You can find the current fontFace parameters in the development version of the theme.json schema.

How to add a font family for a specific block

You can use different font families for different blocks. A common use case is to offer one set of fonts for paragraphs and one for headings or the site title.

You add typography options for individual blocks under settings.blocks.blockname:

settings.blocks.blockname.typography.fontFamilies

Example:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/site-title": {
				"typography": {
					"fontFamilies": [
						{
							"fontFamily": "Helvetica Neue, Helvetica, Arial, sans-serif",
							"slug": "helvetica-arial",
							"name": "Helvetica or Arial",
							other properties...
						}
					]
				}
			}
		}
	}
}

The custom CSS property then uses the block selector (.wp-block-site-title) instead of body:

.wp-block-site-title {
    --wp--preset--font-family--helvetica-arial: Helvetica Neue, Helvetica, Arial, sans-serif;
}

Remember that the font will only be added to the typography panel if the block supports it.

How to apply default fonts to blocks and elements

Reminder: You register the font family in the settings section, and apply it in the styles section.

Here is how you can add a font family for the body in the root level of the styles section in theme.json. This will be the default font family for all your text, unless overridden.

{
	"version": 2,
	"styles": {
		"typography": {
			"fontFamily": "value"
		}
	}
}

You can use any valid CSS as the value for fontFamily. In this example I am using one of the registered presets:

{
	"version": 2,
	"styles": {
		"typography": {
			"fontFamily": "var(--wp--preset--font-family--system-fonts)"
		}
	}
}

CSS output:

body {
    font-family: var(--wp--preset--font-family--system-fonts);
}

You add styles for individual block types under styles.blocks.blockname.typography:

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/site-tagline": {
				"typography": {
					"fontFamily": "value"
				}
			}
		}
	}
}

Or for supported elements under styles.elements.element.typography:

{
	"version": 2,
	"styles": {
		"elements": {
			"h2"": {
				"typography": {
					"fontFamily": "value"
				}
			}
		}
	}
}

How to disable the font family control

There is a way to disable the font family control using theme.json, but it has a huge implication.
If you disable the control on the root level, for the entire site, then WordPress will not register the custom CSS property for the font family. Blocks that use the CSS property for the font family will not use the desired font.

Instead, here is how you can disable the font family control for a specific block by leaving the fontFamilies array empty:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/site-title": {
				"typography": {
					"fontFamilies": []
				}
			}
		}
	}
}

The theme’s default font for the site title will be used, and users will not be able to change it from the interface.

Downloading font files using the Font Library

This shortcut requires WordPress version 6.5. You must also activate a block theme to access the Font Library in the Site Editor.

Open the Typography panel in the Site Editor. Click on “Manage fonts” to open the Font Library:

The Typography panel in the Site Editor has a button for opening the Font Library Modal. The button label is "Mange fonts".
The  Font Library modal has three tab panels: Library, Upload, and Install Fonts. The screenshot shows the installed fonts listed in the Library panel.

Click on Install Fonts. If you have not already enabled Google Fonts, you will be asked to approve the connection. Now you can search for a font family and install it.

WordPress downloads the files to the wp-content/uploads/fonts folder on your WordPress installation, so you need to copy the files from this folder into your themes font folder.

If you use the theme export feature in the Site Editor, you will get a .zip file that contains a theme.json file with the new font family added. But you must update the path to the font file, since it will point to the uploads folder on your installation.

Downloading font files manually

Whether you use Google Fonts or a different font provider, you want to download font files in .woff2 format. – If you want to support older browsers, you may need additional formats.

If you choose a font family on https://fonts.google.com/ and then select the “Download family” option, you will only receive a zip file with .ttf files. To get the .woff2 files, you can use a font converter script or an online converter.
I recommend using this time-saving tool called Google webfonts helper to download the files.

– If your project uses more than one font family, and each has one font file per font-weight and an italic style on top of that, this can result in a large number of files.
You should consider if the design requires all font weights or if using one thin, regular, and bold weight is enough. You can choose to let the browser compensate for the rest of the weights.

Place your font files in your preferred folder in your theme. Don’t forget to include credits, copyright, and license information for the fonts you are bundling!

Notable changes

In the previous versions of this lesson, I shared examples of PHP code using a function called wp_register_webfonts. This function is deprecated and non-functional and should not be used. This functionality evolved into the new Font Library.

Resources

Loading Fonts using theme.json, by 10up