What problem does this address?
When defining element styles in the theme.json or customizing the Global Styles, WP will generate a global CSS for the specified element.
For example, if a theme define a button element style in the theme.json like this:
...
"styles": {
"button": {
"typography": {
"fontWeight": "600"
}
}
}
...
WP will generate this global CSS:
.wp-element-button, .wp-block-button__link { font-weight: 600 }
The valid elements list (and the selectors) are defined in the class-wp-theme-json.php file (ELEMENTS constant). It's also defined in the JS file: package/blocks/src/api/constants.js in the __EXPERIMENTAL_ELEMENTS constant. These are double definitions, one for PHP and the other for JS. The JS constant is used in Site Editor mode to generate real-time global CSS from the Global Styles settings panel.
The valid elements list and the selectors are currently fixed and can't be modified using filters.
In a few cases, theme developers might want to add new selectors to the valid elements list. For example, I want to add .button into the button element selectors.
Original selector: wp-element-button, .wp-block-button__link
It will become: wp-element-button, .wp-block-button__link, .button
When using the :hover pseudo selector, the selector should be: .wp-element-button:hover, .wp-block-button__link:hover, .button:hover.
Currently, there is no way to modify the selectors properly and implement this kind of feature.
I did some workaround on the PHP side by using the wp_theme_json_get_style_nodes filter to check each style node and add the new selectors manually. It seems more like a hack than a proper filter. The snippet is like this:
add_filter(
'wp_theme_json_get_style_nodes',
function( $nodes ) {
foreach ( $nodes as &$node ) {
if ( array( 'styles', 'elements', 'button' ) === $node['path'] ) {
if ( -1 < strpos( $node['selector'], ':hover' ) ) {
// Add selector for button's style node with :hover pseudo selector.
$node['selector'] = $node['selector'] . ', .button:hover';
} else {
// Add selector for button's style node.
$node['selector'] = $node['selector'] . ', .button';
}
}
}
return $nodes;
}
);
That works perfectly both in the front end and Post Editor because the CSS is loaded via PHP.
But this doesn't work in the Site Editor. The Site Editor JS will always replace the global styles with the newly generated CSS according to the Global Styles settings panel. The CSS selector used in the newly generated CSS is the one defined in the __EXPERIMENTAL_ELEMENTS constant which is hard coded and can't be modified.
Also, there's also a minor bug in the JS side __EXPERIMENTAL_ELEMENTS constant.
The selectors for the link element are different from the PHP one.
in PHP: a:where(:not(.wp-element-button))
in JS: a
What is your proposed solution?
I think there should be a new filter or API to modify the element's selectors and make it synced between PHP and JS.
What problem does this address?
When defining element styles in the
theme.jsonor customizing the Global Styles, WP will generate a global CSS for the specified element.For example, if a theme define a button element style in the
theme.jsonlike this:WP will generate this global CSS:
The valid elements list (and the selectors) are defined in the
class-wp-theme-json.phpfile (ELEMENTSconstant). It's also defined in the JS file:package/blocks/src/api/constants.jsin the__EXPERIMENTAL_ELEMENTSconstant. These are double definitions, one for PHP and the other for JS. The JS constant is used in Site Editor mode to generate real-time global CSS from the Global Styles settings panel.The valid elements list and the selectors are currently fixed and can't be modified using filters.
In a few cases, theme developers might want to add new selectors to the valid elements list. For example, I want to add
.buttoninto thebuttonelement selectors.Original selector:
wp-element-button, .wp-block-button__linkIt will become:
wp-element-button, .wp-block-button__link, .buttonWhen using the
:hoverpseudo selector, the selector should be:.wp-element-button:hover, .wp-block-button__link:hover, .button:hover.Currently, there is no way to modify the selectors properly and implement this kind of feature.
I did some workaround on the PHP side by using the
wp_theme_json_get_style_nodesfilter to check each style node and add the new selectors manually. It seems more like a hack than a proper filter. The snippet is like this:That works perfectly both in the front end and Post Editor because the CSS is loaded via PHP.
But this doesn't work in the Site Editor. The Site Editor JS will always replace the global styles with the newly generated CSS according to the Global Styles settings panel. The CSS selector used in the newly generated CSS is the one defined in the
__EXPERIMENTAL_ELEMENTSconstant which is hard coded and can't be modified.Also, there's also a minor bug in the JS side
__EXPERIMENTAL_ELEMENTSconstant.The selectors for the
linkelement are different from the PHP one.in PHP:
a:where(:not(.wp-element-button))in JS:
aWhat is your proposed solution?
I think there should be a new filter or API to modify the element's selectors and make it synced between PHP and JS.