Estimated reading time: 11 minutes
In this lesson you will learn how to use the theme.json typography options, including:
- How to add font families and custom fonts with the webfonts API
- How to add font sizes and use the new responsive fluid typography settings
Prerequisites: Global Styles & theme.json.
Updated August 5, 2022.
I have separated the original lesson into two parts. In the next lesson, I will bring up line height, font weight, text decoration and more.
Font family
Which blocks support font family?
You can add a default font family to the website and to any text based block using the theme.json styles
section.
The following blocks have a font family control in the editor (July 2022, Gutenberg 13.7):
Button, comment author name, comment content, comment date, comment edit link, comment reply link, comments title, heading, list, navigation, post author biography, post author name, post date, post navigation link, post title, query title, read more, site tagline, site title, verse.
Once you have registered the font options they are available in the Font family control in the block’s typography panel:

How to add font families to the block editor
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 creates presets that you can use for the website and for all blocks.
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 values:
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"
},
{
"fontFamily": "Helvetica Neue, Helvetica, Arial, sans-serif",
"slug": "helvetica-arial",
"name": "Helvetica or Arial"
}
]
}
}
}
And 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;
--wp--preset--font-family--helvetica-arial: Helvetica Neue, Helvetica, Arial, sans-serif;
}
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 the body 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"
}
]
}
}
}
}
}
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 add custom fonts from Google Fonts
Gutenberg version 12.8 added the first version of a new webfonts API. The webfonts API supports using local font files that you place in the theme folder. Using local fonts is important for privacy reasons and to comply with GDPR and similar regulations.
- With option one, you add information about the font and font face to theme.json.
- With option two, you use a new PHP function called
wp_register_webfonts()
that you can hook intoafter_setup_theme()
.
The benefit is that you no longer need to enqueue or load the fonts yourself. The new method handles this for you. Both in the editors and on the front of the website.
The code examples below are collected from the Gutenberg GitHub issue.
WP Tavern has also written about the webfonts API.
Downloading the font files
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 amount 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 theme, in your preferred folder. Don’t forget to include credits, copyright and license information for the fonts that you are bundling.
Using the webfonts API with theme.json
Using the webfonts API with theme.json is a little more involved than only using system fonts, because you need to decide which font styles and font weights to include.
The first three settings in theme.json are the same as when you use system fonts: fontFamily
, name
, and slug
. Next, you will add a new setting called fontFace
. This setting represents the @font-face
CSS rule. You can read more about @font-face on mdn web docs.fontFace
includes information about:
- fontFamily. The name of the font.
- fontWeight, as 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.
- src: source, the path to the local file.
If you want to load two separate font files, for example, one for normal and one for italic, you include them as separate settings inside fontFace
, separated by curly brackets and a comma.
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",
"fontStyle": "normal",
"fontStretch": "normal",
"src": [ "file:./assets/fonts/SourceSerifPro-regular.woff2" ]
},
{
"fontFamily": "Source Serif Pro",
"fontWeight": "400",
"fontStyle": "italic",
"fontStretch": "normal",
"src": [ "file:./assets/fonts/SourceSerifPro-italic.woff2" ]
}
]
}
]
}
}
}
Remember to update the path to the files!
Using the webfonts API with PHP
I want to mention this method even though it is not strictly related to theme.json.
The PHP function wp_register_webfonts()
uses the same arguments as the fontFace
setting that I wrote about above, placed inside a nested array.
This function is only available if Gutenberg is active. It is not included in WordPress core (July 2022, WordPress 6.0.1).
Note that the formatting is slightly different, where -
is used in the parameter names instead of camelCase: fontFamily
becomes font-family
.
Example:
add_action( 'after_setup_theme', function() {
/* If the function does not exist, return early: */
if ( ! function_exists( 'wp_register_webfonts' ) ) {
return;
}
wp_register_webfonts(
array(
array(
'font-family' => 'Source Serif Pro',
'font-weight' => '400',
'font-style' => 'normal',
'font-stretch' => 'normal',
'src' => array( 'file:./assets/fonts/SourceSerifPro-regular.woff2' ),
),
array(
'font-family' => 'Source Serif Pro',
'font-weight' => '400',
'font-style' => 'italic',
'font-stretch' => 'normal',
'src' => array( 'file:./assets/fonts/SourceSerifPro-italic.woff2' ),
),
)
);
} );
Font size
Which WordPress blocks support font sizes?
Quite a few blocks have support for font size controls in the editor (July 2022, Gutenberg 13.7):
Button, code, comment author name, comment content, comment date, comment edit link, comment reply link, comments pagination, comments title, group, heading, list, navigation, paragraph, post author, post author name, post comments count, post comments form, post comments link, post date, post excerpt, post navigation link, post terms, post title, preformatted, pull quote, query pagination, query title, quote, read more, site tagline, site title, table, term description, verse.
Default font sizes
Similar to how I described the default color palette in the previous lesson, WordPress adds the default font sizes with CSS custom properties. You can not remove them, but you can assign new values.
The default font sizes in the editor were updated in Gutenberg version 12.2. The new font sizes are included in WordPress 5.9.0.
The normal font size was removed, and huge was renamed x-large (extra large). There are fallbacks implemented for these two sizes. GitHub Pull request.
--wp--preset--font-size--small: 13px;
--wp--preset--font-size--medium: 20px;
--wp--preset--font-size--large: 36px;
--wp--preset--font-size--x-large: 42px;
How to add new font sizes using theme.json
Font size settings for the website and all blocks are added to theme.json under settings.typography.fontSizes
.
The basic key and value pairs used in fontSizes
are:
size:
Any valid CSS font size value.slug:
The unique identifier, that WordPress uses in the CSS custom property.name:
The visible name in the editor (optional).
The default font size "small"
has the value 13px
and the CSS custom property is--wp--preset--font-size--small
. You can change the value of "small"
by registering a new size using the same slug
:
{
"version": 2,
"settings": {
"typography": {
"fontSizes": [
{
"slug": "small",
"size": "1rem",
"name": "Small"
}
]
}
}
}
Adding a font size option for a specific block
Place your font size array inside settings.blocks.blockname.typography.fontSizes
to make the size available for a specific block. This way, you can limit which font sizes that are selectable for that block:
{
"version": 2,
"settings": {
"blocks": {
"core/button": {
"typography": {
"fontSizes": [
{
"slug": "medium",
"size": "1.5rem",
"name": "medium"
}
]
}
}
}
}
}
The CSS output for the above example uses the class for the text inside the button block,wp-block-button__link
:
.wp-block-button__link {
--wp--preset--font-size--medium: 1.5rem;
}
How to disable the custom font size option
The custom font size option is the input field where users can enter a font size and unit manually:

The option is enabled by default. To disable it, set typography.customFontSize
to false:
{
"version": 2,
"settings": {
"typography": {
"customFontSize": false
}
}
}
How to disable the font size option
Leave the array inside settings.typography.fontSizes
empty to disable the theme.json font size option:
{
"version": 2,
"settings": {
"typography": {
"fontSizes": []
}
}
}
Here is an example of how you can add font sizes, but disable the control for a specific block:
{
"version": 2,
"settings": {
"typography": {
"fontSizes": [
{
"slug": "small",
"size": "1rem",
"name": "Small"
},
{
"slug": "medium",
"size": "1.5rem",
"name": "medium"
}
]
},
"blocks": {
"core/list": {
"typography": {
"fontSizes": []
}
}
}
}
}
Fluid typography with Gutenberg
– Now we have arrived at the new and upcoming theme.json changes 🎉.
From Gutenberg version 13.8, you can use a predefined typography scale to reduce or increase the font size depending on the browser window width using clamp().
– The first version of this feature uses a set scale and widths but the Gutenberg contributors are already working on improvements that will allow us to define our own.
Fluid typography is disabled by default and you need to enable it by setting “fluid": true
under settings.typography:
{
"version": 2,
"settings": {
"typography": {
"fluid": true
}
}
}
Notably, as soon as fluid
is enabled, WordPress adds clamp()
to the default font sizes:
--wp--preset--font-size--small: clamp(9.75px, 0.609375rem + ((1vw - 7.68px) * 1.172), 19.5px);
--wp--preset--font-size--medium: clamp(15px, 0.9375rem + ((1vw - 7.68px) * 1.803), 30px);
--wp--preset--font-size--large: clamp(27px, 1.6875rem + ((1vw - 7.68px) * 3.245), 54px);
--wp--preset--font-size--x-large: clamp(31.5px, 1.96875rem + ((1vw - 7.68px) * 3.786), 63px);
To add sizes you need to define a min and max value in addition to the size, name and slug attributes. The accepted units for the fluid typography settings are px
, em
and rem
.
Example:
"fluid": {
"min": "value",
"max": "value"
}
{
"version": 2,
"settings": {
"typography": {
"fluid": true,
"fontSizes": [
{
"slug": "small",
"size": "1rem",
"name": "Small",
"fluid": {
"min": "1rem",
"max": "1.75rem"
}
}
]
}
}
}
- The so called “preferred value” is the value you add to
size
- The minimum size is used below 768px
- The maximum size is used above 1600px
- The default scale factor is 1
You can also disable it for specific blocks:
{
"version": 2,
"settings": {
"blocks": {
"core/paragraph": {
"typography": {
"customFontSize": false
}
}
}
}
}
From Gutenberg version 13.9 (unreleased at the time of writing this), you can mix fluid and regular font sizes by setting fluid to false inside the font size declaration:
{
"version": 2,
"settings": {
"typography": {
"fluid": true,
"fontSizes": [
{
"slug": "small",
"size": "1rem",
"name": "Small",
"fluid": {
"min": "1rem",
"max": "1.75rem"
}
},
{
"slug": "large",
"size": "2.5rem",
"name": "Large",
"fluid": false
}
]
}
}
}
Applying the settings
Reminder: When you use theme.json you first need to register your settings and then apply those settings to the website and the blocks in the styles section.
Add font family and size for the website in the root level of the styles section:
{
"version": 2,
"styles": {
"typography": {
"fontFamily": "value",
"fontSize": "value",
}
}
}
You can use any valid CSS. In this example, I have used presets for the system fonts for the body, and medium text size (defaults to 20px).
{
"version": 2,
"styles": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--system-fonts)",
"fontSize": "var(--wp--preset--font-size--medium)"
}
}
}
CSS output:
body {
font-family: var(--wp--preset--font-family--system-fonts);
font-size: var(--wp--preset--font-size--medium);
}
You add styles for individual block types under styles.blocks.blockname.typography
:
{
"version": 2,
"styles": {
"blocks": {
"core/site-tagline": {
"typography": {
"fontFamily": "value",
"fontSize": "value",
}
}
}
}
}
Resources
Typography Tools Tracking issue: https://github.com/WordPress/gutenberg/issues/34345
Fluid Typography Option: https://github.com/WordPress/gutenberg/issues/24480
Andy Bell:
Fluid typography with CSS clamp
https://css-tricks.com/consistent-fluidly-scaling-type-and-spacing/
James Gilyead & Trys Mudford: Elegantly scale type and space without breakpoints, type scale calculators
Jeremy Church https://type-scale.com/