I stumbled across this tweet from Ana Segota looking for a way to add a CSS box-shadow
to a button’s hover state in WordPress in the theme.json
file.
She’s asking because theme.json
is where WordPress wants us to start moving basic styles for block themes. Traditionally, we’d do any and all styling in style.css
when working in a “classic” theme. But with the default Twenty Twenty-Three (TT3) theme that recently shipped with WordPress 6.1 moving all of its styles to theme.json
, we’re getting closer and closer to being able to do the same with our own themes. I covered this in great detail in a recent article.
I say “closer and closer” because there are still plenty of CSS properties and selectors that are unsupported in theme.json
. For example, if you’re hoping to style something with like perspective-origin
in theme.json
, it just won’t happen — at least as I’m writing this today.
Ana is looking at box-shadow
and, luckily for her, that CSS property is supported by theme.json
as of WordPress 6.1. Her tweet is dated Nov. 1, the same exact day that 6.1 released. It’s not like support for the property was a headline feature in the release. The bigger headlines were more related to spacing and layout techniques for blocks and block themes.
Here’s how we can apply a box-shadow
to a specific block — say the Featured Image block — in theme.json
:
{
"version": 2,
"settings": {},
// etc.
"styles": {
"blocks" :{
"core/post-featured-image": {
"shadow": "10px 10px 5px 0px rgba(0, 0, 0, 0.66)"
}
}
}
}
Wondering if the new color syntax works? Me too! But when I tried — rgb(0 0 0 / 0.66)
— I got nothing. Perhaps that’s already in the works or could use a pull request.
Easy, right? Sure, it’s way different than writing vanilla CSS in style.css
and takes some getting used to. But it is indeed possible as of the most recent WordPress release.
And, hey, we can do the same thing to individual “elements”, like a button. A button is a block in and of itself, but it can also be a nested block within another block. So, to apply a box-shadow
globally to all buttons, we’d do something like this in theme.json
:
{
"version": 2,
"settings": {},
// etc.
"styles": {
"elements": {
"button": {
"shadow": "10px 10px 5px 0px rgba(0,0,0,0.66)"
}
}
}
}
But Ana wants to add the shadow to the button’s :hover
state. Thankfully, support for styling interactive states for certain elements, like buttons and links, using pseudo-classes — including :hover
, :focus
, :active
, and :visited
— also gained theme.json
support in WordPress 6.1.
{
"version": 2,
"settings": {},
// etc.
"styles": {
"elements": {
"button": {
":hover": {
"shadow": "10px 10px 5px 0px rgba(0,0,0,0.66)"
}
}
}
}
}
If you’re using a parent theme, you can certainly override a theme’s styles in a child theme. Here, I am completely overriding TT3’s button styles.
View full code
{
"version": 2,
"settings": {},
// etc.
"styles": {
"elements": {
"button": {
"border": {
"radius": "0"
},
"color": {
"background": "var(--wp--preset--color--tertiary)",
"text": "var(--wp--preset--color--contrast)"
},
"outline": {
"offset": "3px",
"width": "3px",
"style": "dashed",
"color": "red"
},
"typography": {
"fontSize": "var(--wp--preset--font-size--medium)"
},
"shadow": "5px 5px 5px 0px rgba(9, 30, 66, 0.25), 5px 5px 5px 1px rgba(9, 30, 66, 0.08)",
":hover": {
"color": {
"background": "var(--wp--preset--color--contrast)",
"text": "var(--wp--preset--color--base)"
},
"outline": {
"offset": "3px",
"width": "3px",
"style": "solid",
"color": "blue"
}
},
":focus": {
"color": {
"background": "var(--wp--preset--color--contrast)",
"text": "var(--wp--preset--color--base)"
}
},
":active": {
"color": {
"background": "var(--wp--preset--color--secondary)",
"text": "var(--wp--preset--color--base)"
}
}
}
}
}
}
Here’s how that renders:
Another way to do it: custom styles
The recently released Pixl block theme provides another example of real-world usage of the box-shadow
property in theme.json
using an alternative method that defines custom values. In the theme, a custom box-shadow
property is defined as .settings.custom.shadow
:
{
"version": 2,
"settings": {
// etc.
"custom": {
// etc.
"shadow": "5px 5px 0px -2px var(--wp--preset--color--background), 5px 5px var(--wp--preset--color--foreground)"
},
// etc.
}
}
Then, later in the file, the custom shadow
property is called on a button element:
{
"version": 2,
"settings": {
// etc.
},
"styles": {
"elements": {
"button": {
// etc.
"shadow": "var(--wp--custom--shadow) !important",
// etc.
":active": {
// etc.
"shadow": "2px 2px var(--wp--preset--color--primary) !important"
}
},
// etc.
}
}
I’m not totally sure about the use of !important
in this context. My hunch is that it’s an attempt to prevent overriding those styles using the Global Styles UI in the Site Editor, which has high specificity than styles defined in theme.json
. Here’s an anchored link to more information from my previous article on managing block theme styles.
Update: Turns out there was a whole discussion about this in Pull Request #34689, which notes that it was addressed in WordPress 5.9.
And there’s more…
In addition to shadows, the CSS outline
property also gained theme.json
support in WordPress 6.1 and can be applied to buttons and their interactive states. This GitHub PR shows a good example.
"elements": {
"button": {
"outline": {
"offset": "3px",
"width": "3px",
"style": "dashed",
"color": "red"
},
":hover": {
"outline": {
"offset": "3px",
"width": "3px",
"style": "solid",
"color": "blue"
}
}
}
}
You can also find the real examples of how the outline
property works in other themes, including Loudness, Block Canvas, and Blockbase.
Wrapping up
Who knew there was so much to talk about with a single CSS property when it comes to block theming in WordPress 6.1? We saw the officially supported methods for setting a box-shadow
on blocks and individual elements, including the interactive states of a button element. We also checked out how we could override shadows in a child theme. And, finally, we cracked open a real-world example that defines and sets shadows in a custom property.
You can find more detailed in-depth discussions about the WordPress and it’s box-shadow
implementation in this GitHub PR. There is also a GitHub proposal for adding UI directly in WordPress to set shadow values on blocks — you can jump directly to an animated GIF showing how that would work.
Speaking of which, Justin Tadlock recently developed a block that renders a progress bar and integrated box shadow controls into it. He shows it off in this video:
More information
If you’d like to dig deeper into the box-shadow
and other CSS properties that are supported by the theme.json
file in a block theme, here are a couple of resources you can use:
- Managing CSS Styles in a WordPress Block Theme (CSS-Tricks)
- Styling elements in block themes (Dev Notes)
- A Walk-Through of Layout Classes in WordPress 6.1 (Gutenberg Times)
- How to add box-shadows with theme.json (Full Site Editing)
- Box-Shadow: Add UI tools to set box shadow to a block (Gutenberg Pull Request #45507)
- Add box-shadow support for blocks via theme.json (Gutenberg Pull Request #41972)
- Added outline support for blocks via theme.json (Gutenberg Pull Request #43526)
Adding Box Shadows to WordPress Blocks and Elements