-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Part of #20331
@mtias @youknowriad @mcsf @nosolosw provided thoughts for this task.
As we approach the 5.8 cycle and the merge target for the theme.json API, it’s a good time to evaluate what is working and what needs some improvement. All in all, theme.json is responsible for providing configuration settings, global customization on things like text and links, and default style attributes for blocks. The first and last points seem to be fairly well established and their use fairly clear by themes, but the second point needs a bit more formalization.
The latest round of UI design iterations for the Global Styles sidebar puts a bit more emphasis on the style settings of cross-block elements. In light of this and the feedback gathered from themes so far there are a few aspects that can be improved if we clarify these three representations (settings, elements, blocks) a bit better.
To dive into this, let's explore an example of a theme.json that:
- (settings) provides a default color palette and a different color palette for the heading block
- (settings) disables the link color UI in the editor, except for the heading block
- (styles) provides a general link color and a specific link color for the heading block
- (styles) provides different font sizes for each heading configuration (h1-h6)
- (styles) provides a font size for the quote block
- (styles) provides background color and a different font size for links
With the current approach
{
"settings": {
"defaults": {
"color": {
"palette": [ /* default color palette */ ],
"link": false
}
},
"core/heading/h1": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
},
"core/heading/h2": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
},
"core/heading/h3": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
},
"core/heading/h4": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
},
"core/heading/h5": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
},
"core/heading/h6": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
}
},
"styles": {
"root": { // The "body" CSS selector.
"color": {
"link": "hotpink", // The "a" CSS selector within the body.
"background": "value"
}
},
"core/heading/h1": { // The "h1" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/heading/h2": { // The "h2" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/heading/h3": { // The "h3" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/heading/h4": { // The "h4" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/heading/h5": { // The "h5" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/heading/h6": { // The "h6" selector.
"color": {
"link": "green",
"text": "value"
}
},
"core/quote": { // The ".wp-block-quote" selector.
"typography": {
"fontSize": "value"
}
}
}
}
Some of the struggles of the current approach are:
-
We currently have two mechanisms to target DOM elements of a block:
core/heading/h1
to targetH1
elements andstyles.color.link
to targeta
elements within the heading block. -
With the current approach theme authors can only set the color of the links but not the rest of its style properties (text-decoration, border, background-color, etc).
-
For blocks that use block selectors (
core/heading/h1
, etc) there's no way to provide a style or setting for all the configurations of the same block (e.g.: presets forcore/heading
or a particular color style for all headings). theme.json spec: use block names for settings & block selectors for styles #29773 -
The current API for settings & styles promotes block-level APIs while themes have expressed the desire of being able to set things across blocks. An example we've noticed is that current themes with theme.json support use
settings["defaults"]
to target settings but notsettings["core/heading/h1"]
― this is a hint about what are the primary and secondary use cases. See the latest round of mockups for the global styles sidebar as another case in which we want to provide an API to set styles across blocks. -
The current "root" and "defaults" selectors have been reported to be confusing. As we allow composing theme.json objects further (for example, to change the settings for a “page” template or a template part) the presence of a nested “root” object becomes more strange.
Being able to target blocks and elements
The proposal formalizes what we have been aiming to do for Links but extends it to other elements. This makes it more clear that, in addition to blocks, themes and the global styles UI can target specific cross-block elements. Instead of using core/heading/h1
we can use h1
directly (independently from the heading block) and instead of using styles.color.link
we can target a
elements directly.
The idea is that these elements are the same that were shared in the mockups for the global styles sidebar. Initially, these elements are set by core but plugins/themes (or even users through the style variations mechanisms) could be able to register custom ones in the future.
{
"settings": {
"color": {
"palette": [ /* default color palette */ ],
"link": false
},
"blocks": {
"core/heading": {
"color": {
"palette": [ /* heading color palette */ ],
"link": true
}
}
}
},
"styles": {
"color": { // Target the document (body).
"background": "value"
},
"elements": {
"link": { // This is the "a" css selector.
"color": {
"text": "green",
"background": "yellow" // NOT POSSIBLE BEFORE.
},
"typography": {
"fontSize": "value" // NOT POSSIBLE BEFORE.
}
},
"h1": { // This is the "h1" CSS selector.
"typography": {
"fontSize": "value"
}
},
"h2": { // This is the "h2" CSS selector.
"typography": {
"fontSize": "value"
}
},
"h3": { // This is the "h3" CSS selector.
"typography": {
"fontSize": "value"
}
}
// ... and so on
},
"blocks": {
"core/heading": { // This is the "h1, h2, h3, h4, h5, h6" CSS selector.
"elements": {
"link": {
"color": {
"text": "green"
}
}
},
"color": {
"text": "value"
}
},
"core/quote": { // This is the ".wp-block-quote" selector.
"typography": {
"fontSize": "value"
}
}
}
}
}
Note that:
- The distinction between
defaults
androot
is dropped: the settings & styles that lived within them are now top-level keys that target the document (settings => control the whole editor, styles => style the corresponding body/template part/etc). - Settings & styles can still address particular blocks, which are grouped under a
blocks
key (so it's clear that's a secondary API). - There's a new
elements
key instyles
to target the elements suggested by the global styles sidebar mockups, including links or H1-H6 DOM tags. elements
can be nested within a particular block but a particular block can't be nested within another block.- There’s a more clear separation within the style group between the configuration of blocks and the configuration of elements that occur across blocks.
Updating the theme.json shape
While the theme.json file is still experimental the plan is to make changes in a way that the plugin can support the two versions for a couple of weeks (a release or two, depending on the schedule) to both give time to adapt and to allow comparisons. Ultimately, only the version that lands in core will be supported going forward.