While browsing Twitter recently, I stumbled upon an interesting conversation happening between Damon Cook and Joseph Farruggio, who were discussing the pros and cons of theme.json
, a new settings and style engine for WordPress themes.
As seen in the tweet below, Joseph asks “Can you think of an example where writing the CSS in JSON is a better approach than writing the CSS yourself?” Joseph is asking a totally reasonable question that has certainly been on the minds of many WordPress folks, myself included.
In short, he’s asking “Why would we use something like JSON to write CSS if we can just use CSS to write CSS? Why would we introduce a step in between?”
More specifically, why would we do something like this to change a link color:
"blocks": {
"core/group": {
"elements": {
"link": {
":hover": {
"color": {
"text": "red"
}
}
}
}
}
}
Code language: JSON / JSON with Comments (json)
when we can simply do something like this:
.wp-block-group a:hover {
color: red;
}
Code language: CSS (css)
It’s a great question, but the answer is more nuanced than it seems. It’s not as easy as comparing the size of the snippets above.
In short, it’s not about CSS versus JSON or the benefit of one syntax over the other. It’s about whether you want to more cohesively tie together your site’s styles with the WordPress editor and the site and content building experience.
To begin answering Joseph’s question more completely, we need to understand the true aim of theme.json
and who it’s for. Let’s dig in.
But first, some history
Historically, the bulk of styles for a WordPress theme existed in a style.css
file in the theme directory. Here, you would traditionally find some CSS reset styles (to reduce browser inconsistencies), styling for all of the core features (posts, blockquotes, comments, navigations, etc.), architecture styling, and then styles for virtually everything else the theme supported.
This monolithic CSS file was loaded on every page load because it was the source of truth for all styles on your WordPress website. Even if 90% of the styles in the file weren’t relevant to the page, it was loaded in entirety on every page load. Oof!
Enter the block editor
When the WordPress editor was upgraded to the block editor, you needed to go another step further and provide styles for the editor view as well. This required a separate CSS file (editor-style.css
), since only some of the styles from your main style.css file were relevant to the editor view.
To complicate matters even further, the CSS selectors in the editor didn’t match what you wrote for the front end, so you’d end up copying styles to new selectors. 🫠 Simply put, it was a nightmare trying to get visual parity between the front-end and editor view of your site.
And while we were all copying and pasting CSS values to different files, the rest of the web was modernizing CSS with modular approaches, tree shaking (only sending necessary, page-specific styles to the browser), CSS variables, and more.
A smarter way to style
The introduction of WordPress’s Global Settings and Styles file (theme.json
) aims to tackle our CSS woes by being a single source of truth that can generate and deliver CSS more efficiently.
Effectively, theme.json
is a configuration file that dictates styles and settings that alter the look of your theme and features available to its users. For a detailed example, check out the theme.json
file that is shipping with the new default WordPress theme, TwentyTwentyThree.
Settings via theme.json
In classic WordPress themes, we used a functions.php
file to enable and disable different features for our themes. Now, theme.json
provides a canonical way to define the settings of the block editor. These settings allow you to do things like:
- Define CSS variables for colors, typography, gradients, spacing, and more to be used throughout the front end, admin, and CSS files of your site.
- Define which customization options should be made available or hidden from the user.
- Define the default layout of the editor (widths and available alignments).
These settings can be adjusted site-wide, or you can dial in the settings on a per-block basis. This gives you some really powerful fine-grained control over the user experience.
In this simplified example, here’s what it might look like to define settings for a few colors and layout widths.
"settings": {
"color": {
"palette": [
{
"name": "Base",
"slug": "base",
"color": "#fff"
},
{
"name": "Contrast",
"slug": "contrast",
"color": "#170D39"
},
{
"name": "Primary",
"slug": "primary",
"color": "#5F4FF9"
},
]
},
"layout": {
"contentSize": "780px",
"wideSize": "1280px"
},
}
Code language: JSON / JSON with Comments (json)
Now that I’ve defined some values for colors and layout widths, they are available as variables that I can use throughout my theme.json
file to keep my styles nice and cohesive.
These colors will also now be available anywhere in the WordPress editor that uses a color picker. And I can also tap into these colors in my regular ol’ style.css
file via a CSS variable (color: var(--wp--preset--color--base);
) to keep my colors consistent throughout every part of my theme.
I’ve defined a few colors in one location, and now they’re available globally on my site. Sure, it took a little more code than it would have if I wrote it in plain CSS, but look at everything I got in return!
Styles via theme.json
The styles section of theme.json
lets you define styles for core blocks, buttons, links, typography, and more.
By using the theme.json
file to set style properties in a structured and standardized way, the block editor can manage the CSS that comes from different origins (user, theme, and WordPress core) and deliver it where needed throughout the WordPress experience. Parity!
Here’s what it might look like to define the styles for the Post Title block. We’re defining the font size, the font weight, and adding an underline to the post title link.
"styles": {
"blocks": {
"core/post-title": {
"typography": {
"fontSize": "var(--wp--preset--font-size--x-large)",
"fontWeight": "var(--wp--custom--font-weight--semi-bold)"
},
"elements": {
"link": {
"typography": {
"textDecoration": "underline"
}
}
}
}
}
}
Code language: JSON / JSON with Comments (json)
Now, anytime I visit a page where the Post Title block is used, WordPress will generate the CSS I’ve defined above and add it to the page.
Spoiler alert: it’s a design system!
With styles and settings combined, you’re effectively creating a design system for your WordPress theme. You’re dictating the styles and the system in which they operate.
By putting your colors, typography, and spacing into variables, they become portable, reusable, and consumable by the admin, the front-end, and your style.css
file.
Your styles become more than just CSS — they become part of a live, editable, extensible design system with UI controls. This is something CSS or SCSS simply can’t do.
And that’s not all. This new way of generating CSS is also more performant. By moving your styles to theme.json
, the size of your style.css
file is dramatically reduced, improving load times on your site.
When your site needs a style from your theme.json
file, WordPress generates it on the fly and serves only the styles needed. In other words, you don’t have to load all of your site’s styles on every page load anymore, just the critical styles.
And this all just happens ✨automagically✨.
Yeah, but who is it for?
This all sounds great, right? But it’s possible you still just want to write CSS the old fashioned way! Maybe you don’t need to create a design system that can be tapped into globally. Maybe you’re just creating simple sites for yourself and this all seems like overkill.
After creating a few full-site editing themes with it, the ah-ha moment will hit you like a ton of bricks.
However, for those who are creating and distributing WordPress themes, and for those who are crafting solutions where clients or end users need to be able to edit and customize their site, full-site editing and theme.json
will be an absolute game changer. I guarantee after creating a few full-site editing themes with it, the ah-ha moment will hit you like a ton of bricks.
It brings modernization, standardization, customization, and optimization in many of the places WordPress has fallen behind. It creates a desperately-needed design system where there was none before. It brings WordPress closer to its fullest potential.
It’s not perfect, but it’s progress
From the outside looking in, it can be a perplexing and jarring change from the days of simple CSS files. And to be honest, WordPress isn’t doing a stellar job communicating the real world examples and benefits of these powerful features.
I’m still getting used to it myself, but after creating a few themes with deep theme.json
integration, the benefits start to make themselves clear very quickly.
It’s also important to note that all of this will get easier. I think we can all agree that manually creating painfully-long JSON files does not sound like a good time, and so I expect we’ll see some improvements in this space (theme.json
generators, more complete documentation, etc.). But we have to start using it before we know how to make it better.
Thanks to Damon Cook and Joseph Farruggio for starting the conversation that sparked this article. Hopefully digging into these new features and writing about them is as valuable to you as it is to me!
Leave a Reply