Moving Core block styling to JSON

An effort is currently underway in the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party, to streamline and standardize the way that blocks are styled by moving key blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. styling into Theme JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML..  This post lays out the reasoning behind this change and the impact it will have for both themes and block authors going forward.

What is theme.json?

Theme.json is a file which provides a single place to configure the behavior of  themes.

It plays an important role in the Full Site Editing project, by storing information about a site’s appearance and providing this in a machine readable format to be consumed by the Editor interface.

One of the key elements of this is the Global Styles interface within the Site Editor which allows users with a UIUI User interface to allow them to modify the default appearance settings provided by their chosen Theme.

Why use JSON to represent a theme’s styles?

Expressing a theme’s styles in JSON gives us several benefits:

  1. It enables users to modify the visual appearance of their site via the UI provided by Global Styles, without needing to write any CSSCSS Cascading Style Sheets..
  2. We have more control and consistency in how the theme CSS is output, so that we can ensure that user’s settings take priority over theme’s settings, and theme’s settings take priority over coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.’s settings.

What is changing?

To expand the number of customisation options available to users through the Global Styles UI, we need to configure the default visual appearance of blocks using the same tools that will be used to customize these blocks.  This will make it trivial for themes to overwrite the default styles of a block.

In practical terms this means we need to move the rules that define default block appearance from CSS files, to machine readable JSON files, such as `theme.json` & `block.json`.

How can blocks define styles in JSON?

To make the process of moving core block styles into JSON, some new affordances have been created. 

One of these is that the JSON rules for a block can be saved in the block.json file under a new `__experimentalStyles` key.

For example margins on the image block were expressed in CSS like this:

.wp-block-image {
	margin: 0 0 1em 0;
}

Since this change we can now define margins for image blocks in the block.json file like this:

{
	“__experimentalStyle”: {
		“spacing”: {
			“margin”: “0 0 1em 0”;
		}
	}
}

The CSS that is generated from this change is the same as the original CSS file.

For more details on this approach please see “merging block CSS with theme.json styles”. You can also see an example of how this would be implemented in “Block CSS: Move CSS from the stylesheet to the block definition”.

What are the benefits?

Styles are now customizable

The driving force of this change is to enable users to modify the visual appearance of their site via the UI provided by Global Styles, without needing to write any CSS

However this change also has some very important, and useful, side effects.

CSS specificity and performance

For a long time blocks and themes have been struggling with CSS specificity – blocks want to ensure that they provide enough rules that they look good, whilst themes want to override these rules so that different blocks have a consistent appearance (for example ensuring all your buttons look the same). 

This has meant that blocks have to be very careful about the specificity of the selectors in the CSS they provide, to enable themes to override them. 

By expressing visual styles in JSON, and compiling them as part of the main CSS output of global styles, the order and importance of each rule is clear and computable when the theme.json files are processed.

Global Styles processes the different levels of JSON settings, by merging each of these JSON objects together. Once all of the settings are combined, the Global Styles CSS is generated using the final merged result. This means that the resulting CSS only contains the rules the theme needs.

For those not familiar with how rules in Theme JSON files are turned into valid CSS rules here’s a quick refresher. There are x3 “levels” of JSON file:

  • WordPress Core Theme JSON – this holds the base level styles for WordPress.
  • Theme JSON – this is the `theme.json` file from the currently active Theme which provides theme-specific styles.
  • Custom User Styles – these are rules provided by the Global Styles user interface and have the highest level of importance.

When these different JSON representations of styles are merged together, we only preserve the rules for the uppermost setting for each rule before they are converted to CSS rules. 

By moving block CSS rules to JSON we effectively insert a new level into this hierarchy with WordPress Core `theme.json` being overridden by block styles in `block.json` which is overridden by the `theme.json` provided by the theme which is in turn overridden by custom user styles, created in the Global Styles UI.

For clarity the new rules hierarchy is:

  • WordPress Core Theme JSON
  • Block styles in Block JSON
  • Theme styles from Theme JSON
  • Custom User Styles from Global Styles UI.

This also means that the total CSS output of the system will be smaller, which is a performance benefit. 

Exposing default styles

Another benefit of this change is that the default styles for each block are now exposed in the Global Styles UI, before the user makes any changes, so the starting point is obvious and clear. Now that blocks can define most of their styles in JSON, these default styles can be more easily seen and  configured using the Global Styles interface.

Not only are the styles of blocks themselves configurable but the lower level elements used within blocks can also be exposed to the Global Styles UI.

What are elements?

Elements are low level components for themes and blocks, which don’t need the complexity of blocks.

Block composition has not reached a level of infinite composability, hence it is not always possible or good to use, say, the heading block instead of a HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. heading element, or a button block instead of a HTML button element.

Some good examples of these are headings, links and buttons. 

Links are part of many blocks but do not have a block of their own. Headings and buttons are expressed as blocks but many times the block composition limits us, so we’re better off using an HTML heading or button element.

Also, elements are simpler than blocks; they can be used to express semantic features of blocks and enable users to share styles across multiple blocks. For example style rules for the button element will be used in the search block, the file block and the button block.

The number of elements is currently being expanded. Some new elements we expect to add are a caption element and form elements. It is likely some of them will be absorbed into blocks as the block composition APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. gets better, so the implementation of element support is kept at a minimal state.

Putting it all together – exposing default element styles in the UI

If we put these two new concepts (setting default styles in JSON and element styles) together, we can see how the default styles for button elements are now visible in the Global Styles UI:

This helps users to understand the global styles interface more easily as it shows straight away the relationship between these settings and the visual appearance of the block.

Should I set style rules for blocks or for elements?

Theme authors have the option to set styles in `theme.json` for:

  • blocks themselves. 
  • elements within blocks
  • globally for elements shared by blocks.

 It’s important to understand the precedence of each of these options, so you know which one to choose.

  1. Global element styles apply to all instances of an element. These rules will apply across all blocks, to ensure a consistent appearance between all blocks. In some cases this will depend on blocks implementing the elements API to take effect. For example, this would be useful if you wanted to create a style rule that applied to all button elements on your site.
  2. Block styles apply to all instances of that specific block. This is useful if you want to target particular properties of the block itself. For example this could be used to modify the color of all the text within the search block.
  3. Element styles within blocks are the most specific use case. These rules will only apply to elements within a specific block. If users modify global element rules, these the specific customizations for elements within blocks will still take precedence due to their higher specificity, so the user’s global changes won’t apply unless they modify the element settings for that particular block. For this reason this use case should be uncommon. For example, this is useful if you wanted the buttons in your search form to be a different color to the other buttons on your site.

What does this mean for block authors?

Block authors can already take advantage of some of these changes.

Blocks can already start to use the elements API for composing their markup. Right now this only works for the button and captions elements, but as the number of elements is expanded, blocks will be able to compose their markup using these common elements, which will in turn enable them to be better supported by Global Styles.

Blocks can also start to define their style using the `block.json` file, which allows themes to override block styles using `theme.json`, rather than relying on CSS. Styling a block’s supported features within their JSON configuration enables users to modify them via the Global Styles UI.

What does this mean for themers?

This approach gives more tools to themers, to make it easier for themes to have a more consistent style across all blocks without the need for complex CSS. By using the elements section of the theme.json, themes can create style rules that will apply across all blocks that take advantage of these elements, which makes these rules simpler and easier to maintain.

Will this replace the theme’s CSS?

While simple themes may one day be able to replace all their CSS with theme.json settings, it is expected that most themes will still need to provide their own CSS for the more advanced aspects of their design – for example animations.

Is supports > __experimentalStyles the right place for this?

These styles were initially added to supports > __experimentalStyles so that we could begin this work, but ideally these settings would belong in the style key of block.json. There is an open PR to make this possible.

#dev-notes