Deep-diving Into JSON Elements

Notes: This post is part 1 of my proof-of-concepts learning note post for CSS-Tricks article on the JSON elements. Some screenshot images used here are credited to the CSS-Tricks.

There is considerable ongoing efforts in Gutenberg block editor to move the entire style definitions to a single place, i.e. theme.json file. To measure the progress, let’s look at the last three default themes (TT1, TT2, TT3).

The TT1 theme, the first default theme designed for block editor, contains over 5,900 lines of CSS, a JavaScript file, and a … KB size. There is no theme.json file.

The TT2, the first block-based default theme, which includes theme.json file and only over 147 lines of CSS code. The theme.json file contains only 373 lines. Its lead developers had made concerted efforts to make this as the CSS-less theme, however, at that time not all CSS styling rules via theme.json were resolved in Gutenberg site editor. If we look at the TT2 CSS file, those issues included, styling of (i) links and their interactive state, (ii) consistency in styling buttons, and spacing and full-width (age-to-edge) layout.

Now that these styling CSS issues have now been resolved and thus the TT3 is the first default theme, without a single line of theme CSS. It’s theme.json file contains 687 lines of codes. The theme is slim down version of TT2 with added … styles alternatives and has ..KB file size.

At present, not all the CSS styling rules via theme.json has been resolved, and the remaining significant issues are currently being discussed with an aim to fully move all the CSS style rules into the theme.json and consolidate different sources of theme.json into a single Global Style UI via Style Engine and create front-end CSS.

These new developmental features included in WordPress 6.1 have not been widely exposed to most WordPress users due to lack to documentations, notes and tutorials. In this article, I attempt to share my current understanding of these new features with you with some use case examples.

Learning Goals
Part 1: JSON elements API – An Introduction and Overview (this post)
Part 2: Using JSON Elements

The objective of this learning-note post series is to document my research on the topic and retain my memory dump, while preparing a first draft of my article for the CSS-Tricks.

First off, let’s briefly overview JSON element and Pseudo-classes interactive states.

An Overview

One of the main goals of the Gutenberg site editor is to absorb the entire CSS of classic themes by moving theme CSS to theme JSON file. This approach creates different layers of theme JSON files (e.g., Core, block, theme, and user), and thus introduces a new specificity or precedence issue for theme developers.

Since the block themes were introduced in WordPress 5.9how to override Core generated CSS has been one of the main concerns. This problem has been further exacerbated by the frequency of the Gutenberg plugin release cycles, often with moving targets, which are eloquently described in this Make WordPress post.

Theme JSON and theme CSS

Though structurally, both the theme.json and theme CSS look similar. In block themes, theme.json provides a single place to configure and customize its styling.

In this Make WordPress Core blog proposal, Ben Dwyer of Gutenberg development team, eloquently articulates the reasoning of moving the theme CSS into the theme.json file, and its benefit to block theme authors.

One of the major benefits of moving CSS to JSON is that the latter is machine-readable format, and can be exposed in site editor UI, thus allowing users to modify default values and customize the site appearance without writing CSS. It also provides access to block style consistency and better style hierarchy settings, such that the user’s settings take the highest priority over the theme provided theme. json settings.

For theme authors, the theme.json provides options to define most block styles within JSON. Theme users would be able change the site’s default visual appearance by using the Global Styles interface, without writing CSS.

You can find more detail behind the scene discussion notes from the Make WordPress Core post.

HTML element vs JSON Element

The MDN glossary describes elements as “a part of a webpage. In XML and HTML, an element may contain a data item or a chunk of text or an image, or perhaps nothing. A typical element includes an opening tag with some attributes, enclosed text content, and a closing tag.”

This Full Site Editing tutorial explains why there are essential with a table of Gutenberg and WordPress supported selectors.

JSON elements

Previously, only individual heading and link elements were available (e.g., see this sample from TT2 theme). Now, with WordPress 6.1, we can also add Button, Caption, Cite, and Headings element to the theme json file to address the issues of inconsistent style of similar elements across blocks.

JSON elements are low-level components for themes and blocks, that do not need the complexity of blocks. They are a representation of HTML primitives which are currently not within any block and can be used across blocks. How they are supported in the WordPress and Gutenberg is described in the Editor Handbook and this Full Site Editing tutorial.

For example, the links are found in lots of blocks but do not have their own block. By the same token, headings and buttons have their-own blocks, but they are also used across many other blocks as well. Similarly, HTML headings, button, caption, form, and cite elements are also used within the blocks.

A few properties of the JSON elements include:

  • Elements are simpler than blocks
  • They may be shared across the blocks (e.g., buttons rules for file, search, and button blocks)
  • Elements can be styled uniformly regardless of the block to which they belong. Examples, buttons, and forms field.
  • Elements have lower specificity than then the blocks.

While these different layers of theme.json files create a new specific problem, the problem should be solved with the Style Engine API.

The JASON elements are styled at both the upper level (Global) and at the block level. On the top level, they are used with an element selector, and at the block level, the element to be used will be “the element added to the corresponding block”.

Elements style in theme.json and via Editor UI

Prior to WordPress 6.1, elements available in Global Styles UI were limited to

{
  "version": 2,
  "settings": {},
    ...
    ...
  "styles": {
    ...
    ...
    "elements": {
        "h1": {
          "typography": { }
        },
        ...
        ...
        "h6": {
          "typography": { }
        },
        "link": {
          "color": {
            "text": "var(--wp--preset--color--foreground)"
          }
        }
    },
    ...
    ...
  },
  "templateParts": {}
}

The following screenshot shows how typography and color styling can be customized using Global Styles Interface.

Screenshot showing Global Styles UI for typography and color styling customization in WordPress 6.0.2

In WordPress 6.1 new elements have been added. The following partial theme.json example from TTT3 theme

{
  "version": 2,
  "settings": {},
    ...
    ...
  "styles": {
    ...
    ...
    "elements": {
	"button": {
		"border": {
			"radius": "0"
		},
		"color": {
			"background": "var(--wp--preset--color--primary)",
			"text": "var(--wp--preset--color--contrast)"
		},
		":hover": {
			"color": {
				"background": "var(--wp--preset--color--contrast)",
				"text": "var(--wp--preset--color--base)"
			}
		},
		":focus": {
			"color": {
				"background": "var(--wp--preset--color--contrast)",
				"text": "var(--wp--preset--color--base)"
			}
		},
		":active": {
			"color": {
				"background": "var(--wp--preset--color--secondary)",
				"text": "var(--wp--preset--color--base)"
			}
		}
	},
	"h1": {
		"typography": { }		
	},
	"h2": {
		"typography": { }	
	},
	...
        ...
	"h6": {
		"typography": { }	
	},
	"heading": {
		"typography": {
			"fontWeight": "400",
			"lineHeight": "1.4"
		}
	},
	"link": {
		"color": {
			"text": "var(--wp--preset--color--contrast)"
		},
		":hover": {
			"typography": {
				"textDecoration": "none"
			}
		},
		":focus": {
			"typography": {
				"textDecoration": "underline dashed"
			}
		},
		":active": {
			"color": {
				"text": "var(--wp--preset--color--secondary)"
			},
			"typography": {
				"textDecoration": "none"
			}
		},
		"typography": {
			"textDecoration": "underline"
		}
	}
   },
    ...
    ...
  },
  "templateParts": {}
}

This allows to expose element JSON styles into editor > Global styles UI

Screenshot showing global typography elements in WordPress 6.1.

For example, changing buttons and links color styles can be customized directly on the Global Styles interface.

Screenshot showing global links and button elements styling colors options in WordPress 6.1

Benefits

One of the benefit of this approach is that theme developers start using block.json file which can be overridden by theme.json file without using CSS. Users can modify these features using editor Global Styles UI.

Simple themes may be replaced all CSS (eg. TT3, and few others), but more complex and advanced block themes still need provide their own CSS.

How to use?

Theme.json can be used at: – block-level: (define & example) Elements styles within a block are more specific and applies to with a specific block only. Any user modifications applied to Global Styles UI are not applied because of their higher specificity abut only modifications made for the particular block. Eg: coloring search or download buttons differently than rest of the buttons in a site.

  • Elements within blocks (define and example): Applies to a specific block throughout the site (eg. Color within a search block)
  • Globally elements shared by blocks (define & example) This applies to all instances of elements and applies to across the blocks (eg. Buttons, links)

Additional information on JSON elements is available in this Make WordPress proposal and this GitHub ticket.

An use case example using Emptytheme, a blank theme with no style, is described in this section of the CSS-Tricks article.

Style precedence

To overview and get a feel of how specificity works, let’s look the following example of styling a button block.

Rule 1: Site editor’s core theme.json file provides basic default styles.

Let’s start with the Emptytheme, a blank theme with no style, add a button block in a new page. In the example below, the black background color and rounded style rules were applied from the editor’s default settings.

Screenshot showing a button with default (core) style. (Screenshot credit: CSS-Tricks)

Rule 2: The block theme’s theme.json settings take priority over the core default settings.

Let’s change our theme to TT3 and activate it and if we check the same button block, it looks rectangular with lemon background color.

Screenshot showing with TT3 theme global style. (Screenshot credit: CSS-Tricks)

You will notice, the TT3 global button element style (code snippet here) took the precedence over core’s theme.json styling.

Rule 3: Elements styles within a block are more specific than the theme’s settings.

In the next example, I am using a modified TT3-child theme, where default background color of buttons block are set to red.

Screenshot showing style precedence with block-level element styling. (Screenshot credit: CSS-Tricks)

In the screenshot shown above, all buttons are styled with default state red color at the global-level, however only its search button is modified to use TT3’s default lemon green color.

Rule 4: Custom user styles from Global Styles UI take the highest level of precedence.

Next, change the red background color on the buttons block and the lime green color on the search button with the help of the Global Styles interface.

In the screenshot above, the frontend view shows that the button background is changes to Vivid cyan blue while the background of the search button to Vivid red, with the highest priority.

Style engine

Since the introduction of the block themes in WordPress 5.9, overriding Gutenberg generated different layers of CSS has been a major issue, which is eloquently described in this Make WordPress post.

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.

– Make WordPress Core Blog

To address these problems, a new Style Engine has been introduced in WordPress 6.1 to “provide a single, centralized agent responsible for generating and rendering consistent block supports styles on the client-side and server-side”. As of WordPress 6.1, key improvement to generate core block support for border, color, spacing, typography, and layout styles in the editor and frontend.

Further details on long-term and short-term goals of addressing challenges to generate consistent styling and behind the scene discussion can be found here on Block editor styles: initiatives and goals, with a more recent update. To find out more about Style Engine initiatives, please follow the tracking issue and project board.

Useful Resources

The following is list of references link that I gathered during my brief research. While preparing this post, I have also referred some of the following references extensively.

Element API

Style Engine

Pseudoclass and Pseudoelements