Global styles and the future of CSS in WordPress

One of the flagship features of WordPress’s full-site editing is Global Styles. Let’s dig into why this feature is going to be a complete game-changer.

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!

8 responses to “Global styles and the future of CSS in WordPress”

  1. Barış Ünver Avatar

    I always thought it would be smart to have a theme.css file in addition to theme.json file (or a CSS file with a name set inside the theme.json file), and include the theme’s default FSE-related CSS there. Then WordPress could generate the inline CSS using that file as a boilerplate, plus any customizations made by the user.

    1. Mike McAlister Avatar

      Interesting! I wonder if this could just be accomplished with style.css though? When you move a bulk of the style generation to theme.json, there really isn’t much left to add to an additional theme.css file. But I’d be curious to know more about your thoughts!

      1. Barış Ünver Avatar

        The style.css file might be too crowded for existing themes, plus the defaults won’t serve any purpose (because even if the user doesn’t change any settings, they’ll be printed as inline CSS) while still being loaded from within the style.css file. And if the theme would have a ton of default theme styles, it would most definitely bloat the style.css file.

        With the theme.css file idea, that file wouldn’t be loaded/injected into the front-end; it would only serve as a set of default theme styles which would then allow WP core to interpret all theme styles (default styles from theme.css & customized styles from the database) to be printed as inline CSS.

  2. Nahuai Badiola Avatar

    Great summary Mike.

    I couldn’t agree more. Having a standard (that works on the editor and frontend) is great and the “pain” of having to create long JSON files will be reduce when generators fill that gap, as you mentioned.

    Indeed I’m already using some, one of them I’m sure you know it first hand. 😉

  3. Jeff at LiveCanvas Avatar

    [spolier alert: strong opinion]

    Hello Mike,
    I think you are doing a fantastic job illustrating modern WP techniques and you made me realize much better what is the sense of theme.json.

    Personally I’m not a totally sold fan of Gutenberg but I perfectly see where it can shine: to give content creators total control, within reasonably set boundaries.
    Which is awesome.

    What in my opinion is not that great, is that such educated users could get even more distant to understanding standard HTML and CSS – which is a skill that can come always useful later in life (dad’s note LOL).

    Another point, for those folks like me who love CSS utility frameworks à la Tailwind / latest Bootstrap, is that all this need for adding CSS is not so relevant anymore. Something we try to tackle with our picostrap project is to give SASS to the people, also allowing them to customize Bootstrap’s SASS variables on the fly via the Customizer.
    But of course, it’s a totally different goal, aimed at more “technical” users.

  4. Stefan Avatar
    Stefan

    Thank you fo this contribution to the WordPress space Mike. I noticed that you don’t use hover in your button styling. How/where do you suggest we add such changes?

    1. Mike McAlister Avatar

      Hi there, I’ve been waiting for WordPress core to add button hover styling. Right now, the options are limited, but it is being worked on! Once they add that, I’ll implement that for the Ollie theme so everyone can use it. 😎

  5. Hussain Avatar

    I have been looking for a lighweight and clean theme for my blog. Now the search has ended with ollie.

Leave a Reply to Mike McAlister Cancel reply

Your email address will not be published. Required fields are marked *