-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support pseudo selectors on elements
in theme json
#41786
Support pseudo selectors on elements
in theme json
#41786
Conversation
// Set allowed element pseudo selectors based on per element allow list. | ||
foreach ( $valid_element_names as $element ) { | ||
$schema_styles_elements[ $element ] = $styles_non_top_level; | ||
|
||
if ( array_key_exists( $element, static::VALID_ELEMENT_PSEUDO_SELECTORS ) ) { | ||
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $selector ) { | ||
$schema_styles_elements[ $element ][ $selector ] = $styles_non_top_level; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we add a new sub item for each pseudo selector to the schema for each element
(e.g. link
, h1
...etc). Each selector is the key with the valid style values as the value.
// TARGET STRUCTURE | ||
// $schema['styles']['elements']['link'][':hover'] = // allowed pseudo selectors FTW | ||
// $schema['styles']['blocks']['core/button']['elements']['link'][':hover'] = // allowed pseudo selectors for block sub elements FTW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this or add as a comment above the relevant places.
continue; | ||
} | ||
|
||
$result = static::remove_keys_not_in_schema( $input[ $subtree ], $schema[ $subtree ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is why we need to update the schema to allow for pseudo selectors.
* @param array $input Node to process. | ||
* @return array | ||
*/ | ||
protected static function remove_insecure_styles( $input ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can safely remove this function and leave it to the version in WP Core. We've not modified it right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not been modified between 5.9 and 6.0 I think so, though I'd hate to be quoted on that 😄
Should we wait for this PR first? #41306
Is there a reason why it's in 6.1 here if it's not been altered?
// Get a reference to element name from path. | ||
// $metadata['path'] = array('styles','elements','link'); | ||
$current_element = $metadata['path'][ count( $metadata['path'] ) - 1 ]; | ||
|
||
// $output is stripped of pseudo selectors. Readd and process them | ||
// for insecure styles here. | ||
if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) ) { | ||
|
||
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] as $pseudo_selector ) { | ||
if ( isset( $input[ $pseudo_selector ] ) ) { | ||
$output[ $pseudo_selector ] = static::remove_insecure_styles( $input[ $pseudo_selector ] ); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added - here we check whether the current element is in the allowed list for pseudo selectors.
If it is then we loop over all the whitelisted selectors for the given element and append them to the output (having first removed insecure styles as for "normal" properties).
This allows for the following structure to be returned from remove_insecure_properties
:
array(
'styles' => array(
'elements' => array(
'link' => array(
'color' => array(
'text' => 'hotpink',
'background' => 'yellow',
),
':hover' => array(
'color' => array(
'text' => 'red',
'background' => 'blue',
),
),
),
),
),
);
Without this change the :hover
key would not be preserved.
This comment was marked as outdated.
This comment was marked as outdated.
* @param array $input Node to process. | ||
* @return array | ||
*/ | ||
protected static function remove_insecure_styles( $input ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not been modified between 5.9 and 6.0 I think so, though I'd hate to be quoted on that 😄
Should we wait for this PR first? #41306
Is there a reason why it's in 6.1 here if it's not been altered?
When you do, can you teach me? 😄
This might be a long shot, but I was also having trouble with overwriting core's |
If this is limited to theme.json, and not available to controls via the UI as you mention, then I wouldn't have a problem with it as it gives more control to theme developers.
If the intention is to only add color UI controls for Would there be any benefit over regular CSS to be able to add extra styles such as I suppose I'm also wondering if we should restrict/ignore styles with the exception of |
This comment was marked as outdated.
This comment was marked as outdated.
Thanks for your 👀 on this @ramonjd 🙇♂️
Agreed - it would be limited to Theme JSON. We will only expose UI for very specific elements and pseudo selectors.
As I envisage it this is what I'm describing above when I say Theme JSON will be open but the UI will be limited. Did I understand you correctly?
I'm not sure I see one, other than that it would allow all styling related info in a single place instead of split between If we want to restrict this we're actually going to have to write more code than if we don't want to. I'd be interested in wider opinions on this though.
Yes this is a good question. This is for individual block styles right? These are only configurable via the UI correct? In which case we'd want to lock these down to a limited subset of values which the project deems are suitable. The criteria for this would be based on how it impacts a11y, user demand .etc. Again please correct me if I have the wrong end of the stick.
I'd have to charge 😜 |
$pseudo_matches = array(); | ||
preg_match( '/:[a-z]+/', $selector, $pseudo_matches ); | ||
$pseudo_selector = $pseudo_matches[0] ?? null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀 needed here on the regex which intends to match a pseudo selector within a selector.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't correctly match pseudoelements like ::first-letter
and mixed states such as :active:hover
, but it also doesn't have to at this point. Other than that, it looks good.
elements: { | ||
link: | ||
'h1 ' + | ||
ELEMENTS.link + | ||
',h2 ' + | ||
ELEMENTS.link + | ||
',h3 ' + | ||
ELEMENTS.link + | ||
',h4 ' + | ||
ELEMENTS.link + | ||
',h5 ' + | ||
ELEMENTS.link + | ||
',h6 ' + | ||
ELEMENTS.link, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could see no reason that we needed this. The element selector rules seemed to be generated ok without it.
'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}' + | ||
'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}a{color: blue;}a:hover{color: orange;}a:focus{color: orange;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color: red;}h1 a:focus,h2 a:focus,h3 a:focus,h4 a:focus,h5 a:focus,h6 a:focus{color: red;}' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes need careful reviewing to ensure the expected selectors are accurate and the actual output is also suitable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks reasonable to me
if ( declarations.length === 0 ) { | ||
return; | ||
if ( declarations?.length ) { | ||
ruleset = ruleset + `${ selector }{${ declarations.join( ';' ) };}`; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we aborted here. Now we must continue in order to ensure that pseudo selectors can be processed later on.
Yes! I just wanted to make sure I had understood things correctly 😄
Good point. I'm just wondering if, by being permissive in the styles we allow inside a pseudo block, we'd cause havoc to theme authors later should we ever change or restrict them. Maybe some theme.json elders can chime in here 😄
Yeah, I was thinking of anywhere where we'd set a link:hover color (global, blocks styles in the post editor) via the UI. Restricting at this level sounds like a reasonable compromise 👍 |
This commit backports the original PRs from Gutenberg repository: * [WordPress/gutenberg#40260 #40260 Add support for button elements to theme.json] * [WordPress/gutenberg#40889 #40889 Theme Json: Don't output double selectors for elements inside blocks] * [WordPress/gutenberg#41140 #41140 Global Styles: Add support for caption elements] * [WordPress/gutenberg#41160 #41160 Global Styles: Load block CSS conditionally] * [WordPress/gutenberg#41240 #41240 Global Styles: Button Element: update button element selector] * [WordPress/gutenberg#41335 #41335 Duotone: Fix CSS Selectors rendered by theme.json duotone/filter settings for blocks on public pages] * [WordPress/gutenberg#41446 #41446 Block styles: Account for style block nodes that have no name] * [WordPress/gutenberg#41696 #41696 Global Styles: Allow references to values in other locations in the tree] * [WordPress/gutenberg#41753 #41753 Elements: Add an API make it easier to get class names] * [WordPress/gutenberg#41786 #41786 Support pseudo selectors on elements in theme json] * [WordPress/gutenberg#41822 #41822 Elements: Button - Fix element selectors] * [WordPress/gutenberg#41981 #41981 Global Styles: Add support for heading elements] * [WordPress/gutenberg#42072 #42072 Fix link element hover bleeding into button element default styles] * [WordPress/gutenberg#42096 #42096 Add visited to link element allowed pseudo selector list] * [WordPress/gutenberg#42669 #42669 Link elements: Add a :where selector to the :not to lower specificity] * [WordPress/gutenberg#42776 #42776 Theme JSON: Add a static $blocks_metadata data definition to the Gutenberg instance of WP_Theme_JSON] * [WordPress/gutenberg#43088 #43088 Pseudo elements supports on button elements] * [WordPress/gutenberg#43167 #43167 Theme_JSON: Use existing append_to_selector for pseudo elements] * [WordPress/gutenberg#43988 #43988 Styles API: Fixed selectors for nested elements] Props onemaggie, bernhard-reiter, cbravobernal, mmaattiiaass, scruffian, andraganescu, dpcalhoun, get_dave, Mamaduka, SergeyBiryukov. See #56467. git-svn-id: https://develop.svn.wordpress.org/trunk@54118 602fd350-edb4-49c9-b593-d223f7449a82
This commit backports the original PRs from Gutenberg repository: * [WordPress/gutenberg#40260 #40260 Add support for button elements to theme.json] * [WordPress/gutenberg#40889 #40889 Theme Json: Don't output double selectors for elements inside blocks] * [WordPress/gutenberg#41140 #41140 Global Styles: Add support for caption elements] * [WordPress/gutenberg#41160 #41160 Global Styles: Load block CSS conditionally] * [WordPress/gutenberg#41240 #41240 Global Styles: Button Element: update button element selector] * [WordPress/gutenberg#41335 #41335 Duotone: Fix CSS Selectors rendered by theme.json duotone/filter settings for blocks on public pages] * [WordPress/gutenberg#41446 #41446 Block styles: Account for style block nodes that have no name] * [WordPress/gutenberg#41696 #41696 Global Styles: Allow references to values in other locations in the tree] * [WordPress/gutenberg#41753 #41753 Elements: Add an API make it easier to get class names] * [WordPress/gutenberg#41786 #41786 Support pseudo selectors on elements in theme json] * [WordPress/gutenberg#41822 #41822 Elements: Button - Fix element selectors] * [WordPress/gutenberg#41981 #41981 Global Styles: Add support for heading elements] * [WordPress/gutenberg#42072 #42072 Fix link element hover bleeding into button element default styles] * [WordPress/gutenberg#42096 #42096 Add visited to link element allowed pseudo selector list] * [WordPress/gutenberg#42669 #42669 Link elements: Add a :where selector to the :not to lower specificity] * [WordPress/gutenberg#42776 #42776 Theme JSON: Add a static $blocks_metadata data definition to the Gutenberg instance of WP_Theme_JSON] * [WordPress/gutenberg#43088 #43088 Pseudo elements supports on button elements] * [WordPress/gutenberg#43167 #43167 Theme_JSON: Use existing append_to_selector for pseudo elements] * [WordPress/gutenberg#43988 #43988 Styles API: Fixed selectors for nested elements] Props onemaggie, bernhard-reiter, cbravobernal, mmaattiiaass, scruffian, andraganescu, dpcalhoun, get_dave, Mamaduka, SergeyBiryukov. See #56467. Built from https://develop.svn.wordpress.org/trunk@54118 git-svn-id: http://core.svn.wordpress.org/trunk@53677 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit backports the original PRs from Gutenberg repository: * [WordPress/gutenberg#40260 #40260 Add support for button elements to theme.json] * [WordPress/gutenberg#40889 #40889 Theme Json: Don't output double selectors for elements inside blocks] * [WordPress/gutenberg#41140 #41140 Global Styles: Add support for caption elements] * [WordPress/gutenberg#41160 #41160 Global Styles: Load block CSS conditionally] * [WordPress/gutenberg#41240 #41240 Global Styles: Button Element: update button element selector] * [WordPress/gutenberg#41335 #41335 Duotone: Fix CSS Selectors rendered by theme.json duotone/filter settings for blocks on public pages] * [WordPress/gutenberg#41446 #41446 Block styles: Account for style block nodes that have no name] * [WordPress/gutenberg#41696 #41696 Global Styles: Allow references to values in other locations in the tree] * [WordPress/gutenberg#41753 #41753 Elements: Add an API make it easier to get class names] * [WordPress/gutenberg#41786 #41786 Support pseudo selectors on elements in theme json] * [WordPress/gutenberg#41822 #41822 Elements: Button - Fix element selectors] * [WordPress/gutenberg#41981 #41981 Global Styles: Add support for heading elements] * [WordPress/gutenberg#42072 #42072 Fix link element hover bleeding into button element default styles] * [WordPress/gutenberg#42096 #42096 Add visited to link element allowed pseudo selector list] * [WordPress/gutenberg#42669 #42669 Link elements: Add a :where selector to the :not to lower specificity] * [WordPress/gutenberg#42776 #42776 Theme JSON: Add a static $blocks_metadata data definition to the Gutenberg instance of WP_Theme_JSON] * [WordPress/gutenberg#43088 #43088 Pseudo elements supports on button elements] * [WordPress/gutenberg#43167 #43167 Theme_JSON: Use existing append_to_selector for pseudo elements] * [WordPress/gutenberg#43988 #43988 Styles API: Fixed selectors for nested elements] Props onemaggie, bernhard-reiter, cbravobernal, mmaattiiaass, scruffian, andraganescu, dpcalhoun, get_dave, Mamaduka, SergeyBiryukov. See #56467. Built from https://develop.svn.wordpress.org/trunk@54118 git-svn-id: https://core.svn.wordpress.org/trunk@53677 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Added the Needs Dev Note label in case this needs a dev note (either individual or as part of a "misc" dev note) for WP 6.1 release. |
I mentioned it in this post: https://make.wordpress.org/core/?p=98557&preview=true |
Thanks @scruffian. Might it be worth adding the #dev-notes tag to that post? |
This commit backports the original PRs from Gutenberg repository: * [WordPress/gutenberg#40260 #40260 Add support for button elements to theme.json] * [WordPress/gutenberg#40889 #40889 Theme Json: Don't output double selectors for elements inside blocks] * [WordPress/gutenberg#41140 #41140 Global Styles: Add support for caption elements] * [WordPress/gutenberg#41160 #41160 Global Styles: Load block CSS conditionally] * [WordPress/gutenberg#41240 #41240 Global Styles: Button Element: update button element selector] * [WordPress/gutenberg#41335 #41335 Duotone: Fix CSS Selectors rendered by theme.json duotone/filter settings for blocks on public pages] * [WordPress/gutenberg#41446 #41446 Block styles: Account for style block nodes that have no name] * [WordPress/gutenberg#41696 #41696 Global Styles: Allow references to values in other locations in the tree] * [WordPress/gutenberg#41753 #41753 Elements: Add an API make it easier to get class names] * [WordPress/gutenberg#41786 #41786 Support pseudo selectors on elements in theme json] * [WordPress/gutenberg#41822 #41822 Elements: Button - Fix element selectors] * [WordPress/gutenberg#41981 #41981 Global Styles: Add support for heading elements] * [WordPress/gutenberg#42072 #42072 Fix link element hover bleeding into button element default styles] * [WordPress/gutenberg#42096 #42096 Add visited to link element allowed pseudo selector list] * [WordPress/gutenberg#42669 #42669 Link elements: Add a :where selector to the :not to lower specificity] * [WordPress/gutenberg#42776 #42776 Theme JSON: Add a static $blocks_metadata data definition to the Gutenberg instance of WP_Theme_JSON] * [WordPress/gutenberg#43088 #43088 Pseudo elements supports on button elements] * [WordPress/gutenberg#43167 #43167 Theme_JSON: Use existing append_to_selector for pseudo elements] * [WordPress/gutenberg#43988 #43988 Styles API: Fixed selectors for nested elements] Props onemaggie, bernhard-reiter, cbravobernal, mmaattiiaass, scruffian, andraganescu, dpcalhoun, get_dave, Mamaduka, SergeyBiryukov. See #56467. Built from https://develop.svn.wordpress.org/trunk@54118
I can't see that post @scruffian. |
WP 6.1 Dev noteIn 6.1 support has been added to allow developers to define styles for pseudo classes (e.g. Support for this feature is available both for root level elements and also for elements on per-block basis. To add these styles, include the appropriate pseudo class (prepended with a semicolon) in your style definitions and then nest additional styles rules within this to define how your element should look when the pseudo class is active: {
"elements": {
"link": {
"color": {
"text": "green"
},
":hover": {
"color": {
"text": "hotpink"
}
}
}
}
} This will result in the following CSS being output in a Theme (please note actual output may vary): a {
color: green;
}
a:hover {
color: hotpink;
} This functions similarly at a block level, the only difference being the rules should be applied to the {
"blocks": {
"core/group": {
"elements": {
"link": {
":hover": {
"color": {
"text": "red"
}
}
}
}
}
}
} In this case .wp-block-group a:hover {
color: red;
} At the current time support for this feature is intentionally limited to only |
This commit backports the original PRs from Gutenberg repository: * [WordPress/gutenberg#40260 #40260 Add support for button elements to theme.json] * [WordPress/gutenberg#40889 #40889 Theme Json: Don't output double selectors for elements inside blocks] * [WordPress/gutenberg#41140 #41140 Global Styles: Add support for caption elements] * [WordPress/gutenberg#41160 #41160 Global Styles: Load block CSS conditionally] * [WordPress/gutenberg#41240 #41240 Global Styles: Button Element: update button element selector] * [WordPress/gutenberg#41335 #41335 Duotone: Fix CSS Selectors rendered by theme.json duotone/filter settings for blocks on public pages] * [WordPress/gutenberg#41446 #41446 Block styles: Account for style block nodes that have no name] * [WordPress/gutenberg#41696 #41696 Global Styles: Allow references to values in other locations in the tree] * [WordPress/gutenberg#41753 #41753 Elements: Add an API make it easier to get class names] * [WordPress/gutenberg#41786 #41786 Support pseudo selectors on elements in theme json] * [WordPress/gutenberg#41822 #41822 Elements: Button - Fix element selectors] * [WordPress/gutenberg#41981 #41981 Global Styles: Add support for heading elements] * [WordPress/gutenberg#42072 #42072 Fix link element hover bleeding into button element default styles] * [WordPress/gutenberg#42096 #42096 Add visited to link element allowed pseudo selector list] * [WordPress/gutenberg#42669 #42669 Link elements: Add a :where selector to the :not to lower specificity] * [WordPress/gutenberg#42776 #42776 Theme JSON: Add a static $blocks_metadata data definition to the Gutenberg instance of WP_Theme_JSON] * [WordPress/gutenberg#43088 #43088 Pseudo elements supports on button elements] * [WordPress/gutenberg#43167 #43167 Theme_JSON: Use existing append_to_selector for pseudo elements] * [WordPress/gutenberg#43988 #43988 Styles API: Fixed selectors for nested elements] Props onemaggie, bernhard-reiter, cbravobernal, mmaattiiaass, scruffian, andraganescu, dpcalhoun, get_dave, Mamaduka, SergeyBiryukov. See #56467. git-svn-id: https://develop.svn.wordpress.org/trunk@54118 602fd350-edb4-49c9-b593-d223f7449a82
What?
As part of work towards #38277, this PR enables
theme.json
support forelements
(both top and block level) to contain pseudo selectors in the form:Currently this PR imposes a whitelist which governs which psuedo selectors are available to be used on which elements. It looks like this but could be augmented as required:
Please note that once an element is "open" to a given pseudo selector all valid stlye properties are available to be changed. For example the following is valid whether you should do it or not:
My personal preference would be to lock things down to a bear minimum to avoid a11y issues but I guess perhaps we'll want things open to developers to make those choices just like they do every day in CSS. We can limit user choices but choosing not to expose UI controls for every possible style property.
Why?
This is low level work to support styling of interactivity states in the editor and front end.
How?
Update the sanitization routines to allow various pseudo selectors on a per
element
basis. For now we only supportlink
.Todo
WP_Theme_JSON_Gutenberg::remove_insecure_properties
to allow for pseudo selectors.elements
pseudo selector support.pseudo
(note: this task will never be completed)Create an allow/whitelist for per element pseudo selectors for use on client side (or pass the existing config value from PHP)- this can be handled in a followup.Testing Instructions
Stress testing
Note this PR is being stress tested by applying it various Themes.
Testing with Archeo test PR
I have created an example PR on the Archeo theme to test this out. You can try that by running a copy of Archeo with that PR checked out.
Manual testing
theme.json
file.link
element at top level:a
elements have ahotpink
color when you hover over them on both editor and frontend.:target
.button
.Please be sure to check in both the Post and the Site Editor.
Screenshots or screencast
Editor
Frontend
Authors
Co-authored-by: Andrei Draganescu <me@andreidraganescu.info>, Adam Zielinski, Ben Dwyer <ben@scruffian.com>