The main change in block themes is a JSON file that defines preset options and default appearance settings. WordPress then creates CSS based on this file and the choices we make in the editor.

The number of options that can be defined in the JSON file is growing, to the point that most design decisions can be made that way. Does this mean themes do not use CSS anymore? Not at all.

We can keep using CSS, but we must be more precise.

Styles generated by WordPress from the theme’s JSON are very specific. For example, to give a paragraph proper alignment, it can be targeted like this:

.wp-container-1 > :where(:not(.alignleft):not(.alignright))

This targets any element that is a direct child of an element with the class wp-container-1 and does not have the class alignleft or alignright. And it will set its width and horizontal margins.

There is a specificity rule in CSS: if two rules apply to the same element, the most specific one would be used. For example, given this CSS:

p > a { color: green; }
p a { color: blue; }
a { color: red; }

Which colour would the link in this HTML be?

<p>Text with a <a href="/">link</a>.</p>

The answer is green. If the rules were equally specific, it would be red, because it is the last one. But the last one is less specific, it targets all links. The second one is a bit more specific than the first one; it targets links descendants of a paragraph. And the first one is more specific as it targets only links direct siblings of a paragraph, so it will prevail.

It makes sense, as it allows us to define general rules, and then specific ones that will override them.

We can also make use of !important when we want a rule to prevail over other rules set later in our CSS, or more specific rules. But it is a frustrating route to take because when used once, its effects can be unpredictable, and hard — if not impossible — to override when necessary.

Spoiler alert: the styles generated by WordPress from the theme’s JSON also use !important.

How can we avoid it becoming a mess? Generated styles only target default WordPress classes. We can add custom classes and IDs, so we can target something these styles will never do.

It can be messy if we have rules in a theme’s CSS that contradict the theme’s JSON. But that should never be the case. It does not make any sense.

Also, we can load CSS files in our theme for some blocks, which adds some complexity. The rule of thumb should be:

  • To change the default style of the block, use the theme’s JSON
  • To add some variation or class, use a CSS for the block

This is what I chose to do to add a hexagon-shaped clip-path for the profile pic on the about page of my site. I load a CSS for the image block with a specific class, which I added to the block in the editor.

It can be improved by having an option selector in the editor for that specific shape. But it works.

My advice is to learn about selectors and specificity in CSS to work with block themes. Having several sources of rules, some of which we can not edit directly can be a frustrating experience if we are not well-equipped. Brute force will not cut it anymore.