Managing CSS Styles in a WordPress Block Theme
It’s worth reading Ben’s post, but the meat is in this quote:
Overriding CSS, whether layout, preset, or block styles, presents an obstacle to integration and interoperability: visual parity between the frontend and editor becomes more difficult to maintain, upgrades to block internals may conflict with overrides. Custom CSS is, furthermore, less portable across other block themes.
By encouraging theme authors to use
theme.json API where possible, the hierarchy of “base > theme > user” defined styles can be resolved correctly.
One of the major benefits of moving CSS to JSON is that JSON is a machine-readable format, which means it can be exposed in the WordPress Site Editor UI by fetching an API, thus allowing users to modify default values and customize a site’s appearance without writing any CSS at all. It also provides a way to style blocks consistently, while providing a structure that creates layers of specificity such that the user settings take the highest priority over those defined in
theme.json. That interplay between theme-level styles in
theme.json and the user-defined styles in the Global Styles UI is what makes the JSON approach so appealing.
Developers maintain consistency in JSON, and users gain flexibility with code-less customizations. That’s a win-win.
For example, links are styled in the
elements object but are not a block in their own right. But a link can be used in a block and it will inherit the styles defined on the
elements.link object in
theme.json. This doesn’t fully encapsulate the definition of an element, though, as some elements are also registered as blocks, such as the Heading and Button blocks — but those blocks can still be used within other blocks.
As you can see, it’s still early days and plenty still needs to move from the Gutenberg plugin into WordPress Core. But you can see how quick it would be to do something like style all headings in a theme globally without hunting for selectors in CSS files or DevTools.
Further, you can also start to see how the structure of
theme.json sort of forms layers of specificity, going from global elements (e.g.
headings) to individual elements (e.g.
h1), and block-level styles (e.g.
h1 contained in a block).
Let’s keep talking about CSS specificity. I mentioned earlier that the JSON approach to styling establishes a hierarchy. And it’s true. Styles that are defined on JSON elements in
theme.json are considered default theme styles. And anything that is set by the user in the Global Styles UI will override the defaults.
In other words: user styles carry more specificity than default theme styles. Let’s take a look at the Button block to get a feel for how this works.
OK, we know that WordPress Core ships with some light styling. Now, I’m going to switch to the default TT3 theme from WordPress 6.1 and activate it. If I refresh my page with the button, the button changes styles.
Now I am going to modify TT3 by overriding it with a
theme.json file in a child theme, where the default background color of the Button block is set to red.
But notice the search button in that last screenshot. It should be red, too, right? That must mean it is styled at another level if the change I made is at the global level. If we want to change both buttons, we could do it at the user level using the Global Styles UI in the site editor.
We changed the background color of both buttons to blue and modified the text as well using the Global styles UI. Notice that the blue from there took precedence over the theme styles!
That’s a very quick, but good, idea of how CSS specificity is managed in WordPress block themes. But it’s not the complete picture because it’s still unclear where those styles are generated. WordPress has its own default styles that come from somewhere, consumes the data in
theme.json for more style rules, and overrides those with anything set in Global Styles.
Are those styles inline? Are they in a separate stylesheet? Maybe they’re injected on the page in a
Basically, this is the foundation for establishing a single API that contains all the CSS style rules for a theme, wherever they come from. It cleans up the way WordPress would inject inline styles pre-6.1 and establishes a system for semantic class names.
We talked a bit about JSON elements in the
theme.json file and how they are basically HTML primitives for defining default styles for things like headings, buttons, and links, among others. Now, let’s look at actually using a JSON element and how it behaves in various styling contexts.
JSON elements generally have two contexts: the global level and the block level. The global level styles are defined with less specificity than they are at the block level to ensure that block-specific styles take precedence for consistency wherever blocks are used.
All buttons are styled at the global level (
We can confirm this in DevTools as well. Notice that a class called
.wp-element-button is the selector. The same class is used to style the interactive states as well.
Again, this styling is all happening at the global level, coming from
theme.json. Whenever we use a button, it is going to have the same background because they share the same selector and no other style rules are overriding it.
We could override the button’s background color either in
theme.json (preferably in a child theme since we’re using a default WordPress theme) or in the Global Styles settings in the site editor (no child theme needed since it does not require a code change).
But then the buttons will change all at once. What if we want to override the background color when the button is part of a certain block? That’s where block-level styles come into play.
To understand how we can use and customize styles at the block level, let’s change the background color of the button that is contained in the Search block. Remember, there is a Button block, but what we’re doing is overriding the background color at the block level of the Search block. That way, we’re only applying the new color there as opposed to applying it globally to all buttons.
To do that, we define the styles on the
styles.blocks object in
theme.json. That’s right, if we define the global styles for all buttons on
styles.elements, we can define the block-specific styles for button elements on
styles.block, which follows a similar structure:
See that? I set the
text properties on
styles.blocks.core/search.elements.button with two CSS variables that are preset in WordPress.
The result? The search button is now red (
--wp--preset--color--quaternary), and the default Button block retains its bright green background.
We can see the change in DevTools as well.
The same is true if we want to style buttons that are included in other blocks. And buttons are merely one example, so let’s look at another one.
Let’s drive all this information home with an example. This time, we will:
First, let’s start with the basic structure for
This establishes the outline for our global and block-level styles.
Let’s add the
headings object to our global styles and apply some styles:
That sets the color for all headings to the preset base color in WordPress. Let’s change the color and font size of Heading 2 elements at the global level as well:
Now we have three levels of styles for Heading 2 elements: all headings, all Heading 2 elements, and Heading 2 elements that are used in the Query Loop block.
You’re probably wondering which JSON elements support which CSS properties, not to mention how you would even declare those. While we wait for official documentation, the best resources we have are going to be the
theme.json files for existing themes. I’m going to provide links to themes based on the elements they customize, and point out what properties are customized.
Be sure to give each
theme.json file a good look because these themes include excellent examples of block-level styling on the
It’s easy to get lost while trying to get around the Site Editor unless you are working day and night inside the tool. The navigation is jumpy and confusing, especially when going from template browsing to template editing to modifying individual blocks.
I’m listing all of the resources I used while researching information for this article.
Thanks for reading! I’d love to hear your own reflections on using the block themes and how you managing your CSS.
If you need help creating a digital marketing strategy for your business, don’t hesitate to contact one of Digidude’s consultants.