How to add text shadows to your WordPress theme (or turn them off)

With every new WordPress release, the gap between what we can design in Figma and what we can build in the Site Editor shrinks a little bit more. The latest step forward is text shadows, which WordPress 7.2 adds to the editor.

Headings and paragraphs get a new “Text shadow” setting in the Typography panel, with two presets from WordPress itself: “Light” and “Strong”. Both are soft, black shadows, which may or may not suit your theme. You can read more about the feature in the dev note on Make WordPress Core.

In this tutorial, we’ll take a look at how the new setting works, how to replace the default presets with your own, and how to turn text shadows off entirely. I’ve tested everything with the WordPress 7.2 beta, which is scheduled for release in early December.

How text shadows work in the editor

The text shadow setting is hidden by default. To find it, select a heading or a paragraph, click the options menu (⋮) in the Typography panel, and choose “Text shadow”. Once a block has a text shadow, the setting is shown in the panel without that extra step.

In a block’s settings, clicking “Text shadow” opens a list of the available presets, along with a preview. There’s no field for entering a shadow of your own in the block settings, but site owners can edit the presets and add new ones in the Site Editor, under “Styles” → “Typography” → “Text shadow presets”. By default, the list contains the “Light” and “Strong” presets included in WordPress, which is why it’s worth replacing them with presets that match your theme.

When a preset is selected, the block gets a class like has-light-text-shadow, which sets the text-shadow property to a CSS variable like --wp--preset--text-shadow--light. Since posts only store the class, you can change what a preset looks like later without having to update any content.

For now, only the Heading and Paragraph blocks support text shadows, but other blocks can be given support too. If you register your own blocks, set textShadow to true under supports.typography in the block’s block.json file. For other core blocks, like the Button block, you can add the same setting with the block_type_metadata filter, which lets you change a block’s block.json settings before it’s registered. The text shadow class is added to the block’s outer element, so depending on the block’s markup, you might need some extra CSS for the shadow to end up where you want it.

How to add your own text shadow presets

Text shadow presets are added in the theme’s theme.json file, just like font sizes and colors. Add a textShadowPresets array to settings.typography, with a name, a slug and a textShadow value for each preset:

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"typography": {
"textShadowPresets": [
{
"name": "Subtle",
"slug": "subtle",
"textShadow": "0 0.05em 0.1em rgba(0, 0, 0, 0.15)"
},
{
"name": "Glow",
"slug": "glow",
"textShadow": "0 0 0.5em rgba(255, 200, 0, 0.6)"
}
]
}
}
}

If you’re using a theme you didn’t make yourself, add the presets in a child theme instead, so they aren’t lost the next time the theme updates. I have a separate tutorial on how to create a child theme of a WordPress block theme.

The textShadow value takes anything the CSS text-shadow property does, including several shadows separated by commas. Using em units for the offset and blur makes the shadow scale with the font size, so the same preset looks right on both a large heading and a small paragraph.

You can also use your theme’s colors in a shadow with the full CSS variable, like 0 0 0.5em var(--wp--preset--color--accent). The shadow then follows the color palette, including in style variations. The var:preset|color|accent shorthand doesn’t work here.

Your presets are listed after the default ones. If you’d rather only show your own, add defaultTextShadowPresets and set it to false:

"typography": {
"defaultTextShadowPresets": false,
"textShadowPresets": [ … ]
}

This removes “Light” and “Strong” from the editor, but WordPress still outputs their CSS, so content that already uses them keeps its shadow.

One thing to watch out for: if you turn off the default presets without adding any of your own, the setting is still shown in the editor, but the only option in it is “None”. If you don’t want any presets, turn text shadows off entirely instead.

How to use a preset in your theme’s styles

The presets aren’t only for the editor. You can also use them in the styles section of theme.json, to give elements a text shadow by default. This gives all headings the “Subtle” shadow:

"styles": {
"elements": {
"heading": {
"typography": {
"textShadow": "var:preset|text-shadow|subtle"
}
}
}
}

The presets are regular CSS variables too, so you can use them in your theme’s stylesheet with var(--wp--preset--text-shadow--subtle).

How to turn off text shadows

If you manage websites for clients, any new design feature is a chance for clients to stray outside the brand guidelines you’ve set up for them. If you’d rather not let users add text shadows at all, set textShadow to false in settings.typography:

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"typography": {
"textShadow": false,
"defaultTextShadowPresets": false
}
}
}

With this, “Text shadow” disappears from the options menu in the Typography panel, and the text shadow presets disappear from “Styles” in the Site Editor. The dev note recommends turning off the default presets too when you turn off the feature, which is why both are set to false. Blocks that already have a text shadow keep it, since the class is saved in the content, but it can no longer be added or changed in the editor.

If you’d like to keep text shadows for headings, but not for running text, you can turn them off for paragraphs only. Add the setting to the paragraph block under settings.blocks instead:

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"blocks": {
"core/paragraph": {
"typography": {
"textShadow": false
}
}
}
}
}

WordPress 7.2 is still in development, and some of the finer details above might change before the planned release in early December. I’ll update the tutorial once it’s out.