Theme.json typography: Font size

In this lesson, you will learn how to add custom font sizes to your theme using theme.json.
To add custom font sizes to theme.json, you need to add an array of sizes to the typography object in the settings section: settings.typography.fontSizes.

WordPress then creates a font size preset with a custom CSS property and a CSS class name for each size. When the user selects the size in the block editor, WordPress adds the class name to the block. Here is an example using the “small” size:

<p class="has-small-font-size">small</p>

.has-small-font-size {
font-size: var(--wp--preset--font-size--small) !important;
}

-wp--preset--font-size--small: 13px;

You can use the CSS variable in the theme.json styles section to set default font sizes for your site and your blocks. You can register different font sizes for different blocks and mix static sizes with fluid (responsive) typography with min and max values.

WordPress adds four default font sizes; from small to extra large. When you add a new size, it is important to know that you are overriding the default sizes. I will describe this in more detail in the lesson.

Prerequisites: Global Styles & theme.json.

All code examples in this lesson assumes that you are using theme.json version 2 or 3. Remember that you must include the version in your .json file.

Level: ,

Estimated reading time: 9 minutes

Last updated

Font size controls in the Typography panel

Each block that supports font sizes has a Typography panel in the block settings sidebar in the editor:

The typography panel with a group of four buttons with text S, M, L and XL.

Font size presets

WordPress displays the font size presets as a group of four buttons with “t-shirt sizes”: S, M, L, and XL. If you register more than five sizes, the block editor shows the sizes in a dropdown since they will not fit on one row:

The typography panel with an expanded drop down that lists custom font sizes: Default, extra small, small, base, medium, and large.

Custom sizes

Besides selecting from your theme’s font size presets, users can set a custom size. The custom sizes are not site-wide; users can only apply them to single blocks. Compared to color palettes, users can not create their own set of reusable font size presets.

The custom size option consists of an input field where the user can enter a value and select a unit: px, em, or rem. Or, they can use a slider that ranges from 0 to 100:

The custom font size control in the Typography panel. The input field shows 13px, and the dropdown where the user selects the unit is opened.

Default font sizes

Here is the short list of the WordPress default sizes, with their CSS custom properties and values:

--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;

Please see “Fluid font sizes” below for the fluid size calculations.

Notable changes
The default font sizes were updated 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.

How to disable font sizes

To disable the font size controls completely, you need to remove both the default font sizes and the option for the custom font size.

Using theme.json version 2 (up to WordPress 6.5):

"settings": {
	"typography": {
		"fontSizes": [],
		"customFontSize": false
	}
}

Using theme.json version 3 (from WordPress 6.6):

"settings": {
	"typography": {
		"defaultFontSizes": false,
		"customFontSize": false
	}
}

defaultFontSizes is a new setting in theme.json version 3, and is enabled by default.

Be aware that even if you disable the controls in the editor, WordPress will output the CSS variables for the default sizes in the editor and on the front of the site.

While you can disable the controls for individual block types, the only way to disable it for theme.json elements is to disable it for the site using the first code example.

There are many reasons why you may want to disable the custom font size option. For example, if you are building a site for a client and do not want them to choose the wrong font size. Or because you do not want the size to be added inline in the style attribute:

<h2 class="wp-block-heading" style="font-size:48px">Custom</h2>

How to add new font sizes using theme.json

You add your custom font sizes 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).
"settings": {
	"typography": {
		"fontSizes": [
			{
				"slug": "extra-small",
				"size": "1rem",
				"name": "Extra small"
			}
		]
	}
}

The control in the Typography panel displays the sizes in the order you register them. So, not by size or alphabetically. If you register fewer than five sizes, WordPress will display them with the t-shirt sizes, no matter what you name your sizes. So you have to ensure that the first size is the smallest, and so on.

Notable changes
From theme.json version 3, you can no longer override the default font sizes. For example, if you want to reuse the name and slug for the small font size, you must disable the default sizes.

How to add a font size 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:

"settings": {
	"blocks": {
		"core/button": {
			"typography": {
				"fontSizes": [
					{
						"slug": "extra-small",
						"size": "1rem",
						"name": "Extra Small"
					}
				]
			}
		}
	}
}

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--extra-small: 1rem;
}

Fluid font sizes

WordPress introduced fluid font sizes in version 6.1 and additional properties in 6.4. Now, you can use a typography scale to reduce or increase the font size depending on the browser window width using clamp().

The calculations for the fluid sizes are part of the typography block support. View the source in WordPress 6.5.

Fluid font sizes are disabled by default, and you enable them by adding “fluid": true to settings.typography:

"settings": {
	"typography": {
		"fluid": true
	}
}

Besides the boolean, there are three optional properties. – Setting either of these properties also enables fluid font sizes without needing the boolean. Use one format or the other.

  • minFontSize: Font sizes below this value will not be re-calculated using clamp(). Sizes that do use clamp() will never go below this size.
  • maxViewportWidth: A px, rem, or em value. Above this width, font sizes will not be fluid.
  • minViewportWidth: A px, rem, or em value. Below this width, font sizes will not be fluid.

If you do not set a maxViewportWidth value, the calculation will use the value from the wideSize in the layout object in theme.json.

In this code example, I have used the default values:

"settings": {
	"typography": {
		"fluid": {
			"minFontSize": "13px",
			"maxViewportWidth": "1600px",
			"minViewportWidth": "320px"
		}
	}
}

The root font size for the calculations is 16px. It is not possible to change this value. If you change it in your custom CSS, the calculations will still use 16px.

As soon as fluid is enabled, WordPress adds clamp() and a fallback value to some of the default font sizes:

--wp--preset--font-size--small: 13px;

--wp--preset--font-size--medium: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.625), 20px);

--wp--preset--font-size--large: clamp(22.041px, 1.378rem + ((1vw - 3.2px) * 1.454), 36px);

--wp--preset--font-size--x-large: clamp(25.014px, 1.563rem + ((1vw - 3.2px) * 1.769), 42px);

As you can see, the clamp is not applied to the small size, which is set to 13px, because it is below the minimum font size.

Note that the custom sizes that the users select in the control in the editor are also updated to use clamp(). This can be important to know if you receive questions about unexpected sizes from your users or clients.

How to add fluid font sizes to theme.json

When you have enabled fluid font sizes in the typography setting, WordPress will use your size and calculate the clamp() values for you. If you have used pixel units, it will transform them into rem.

Relying on WordPress for the calculations is one option, but you can also customize the minimum and maximum values for each size by adding min and max values to each size:

"fluid": {
"min": "value",
"max": "value"
}

You can mix fluid and static values by disabling the fluid option on selected sizes. Add fluid: false to the font size declaration.

Theme.json example:

"settings": {
	"typography": {
		"fluid": true,
		"fontSizes": [
			{
				"slug": "extra-small",
				"size": "1.25rem",
				"name": " Extra small",
				"fluid": {
					"min": "1rem",
					"max": "1.75rem"
				}
			},
			{
				"slug": "xx-large",
				"size": "6rem",
				"name": "XXL",
				"fluid": false
			}
		]
	}
}

Note: The size value is the preferred size in the clamp().

Of course, if you do not want to use the clamp calculation from the block editor, you could add your own clamp() directly as the size value without enabling the fluid setting.

How to apply default font sizes

You can use any valid CSS for the size. You are not limited to using the font size presets that I have talked about in this lesson. For example, you can create your own custom CSS property under settings.custom, and use that CSS variable as the font size value. Just be aware that this type of custom size will not be available in the font size control. -If the user changes the size, they will not be able to change it back easily.

You add a font size for the body at the top level of the theme.json styles section:

"styles": {
	"typography": {
		"fontSize": "1.25rem",
	}
}

In this example, I have used the preset for the medium size:

"styles": {
	"typography": {
		"fontSize": "var(--wp--preset--font-size--medium)"
	}
}

CSS output:

body {
font-size: var(--wp--preset--font-size--medium);
}

You can add styles to block types under styles.blocks.blockname.typography:

"styles": {
	"blocks": {
		"core/site-tagline": {
			"typography": {
				"fontSize": "14px",
			}
		}
	}
}

And to theme.json elements such as headings:

"styles": {
	"elements": {
		"h1": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--x-large)",
			}
		}
	}
}

FAQ

How can I remove the ‘Default’ font size?

The ‘Default’ font size shows in the font size control when your theme registers more than five sizes. It is not possible to remove this option.

  • If you have set a default size for a block, it is used for the ‘Default’ option.
  • If that size is a preset, it will also show in the list of available sizes (with its custom name).

Selecting the default size resets the block to the intended size. In that sense, it works the same way as the reset option.

What should I name my font sizes?

Because many users are familiar with the t-shirt sizes, it may be easier for them if your sizes are named the same way.
The name and slug do not need to match, but be kind to yourself and use combinations that are easy for you to remember when you are creating your designs. Use neutral names that will work for different sizes in different style variations.

What happens to the font sizes if the theme is changed?

When the user switches themes, the font size class name (has-slug-font-size) will still be on the block. But it will only continue working if the new theme has the same slugs, otherwise, there is no CSS to apply to the class name. So, if you are developing more than one theme, it may be best to try to re-use the exact font size slugs. Also, consider what happens if the user switches from a bundled theme, like Twenty Twenty-Four, to your theme.

Resources

For tips about accessible font sizes please see this video presentation by Stefano Minoia: Accessible Fluid Typography in the Block Editor

For selecting responsive font sizes for your theme I recommend the fluid type scale calculator from Utopia.