Skip to content
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

Merged
merged 9 commits into from
Jun 23, 2022

Conversation

getdave
Copy link
Contributor

@getdave getdave commented Jun 17, 2022

What?

As part of work towards #38277, this PR enables theme.json support for elements (both top and block level) to contain pseudo selectors in the form:

{
    "elements": {
        "link": {
            "color": {
                "text": "green"
            },
            ":hover": {
                "color": {
                    "text": "hotpink"
                }
            }
        }
    },
    "blocks": {
        "core/group": {
             "elements": {
                "link": {
                    ":hover": {
                        "color": {
                            "text": "red"
                        }
                    }
                }
            }
        }
    }
}

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:

const VALID_ELEMENT_PSEUDO_SELECTORS = array(
    'link' => array( ':hover', ':focus' ),
);

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:

{
    "elements": {
        "link": {
            "color": {
                "text": "green"
            },
            ":hover": {
                "color": {
                    "text": "hotpink"
                },
                "typography": {
                    "textTransform": "uppercase",
                    "fontSize": "10em"
                }
            }
        }
    }
}

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 support link.

Todo

  • Get WP_Theme_JSON_Gutenberg::remove_insecure_properties to allow for pseudo selectors.
  • Ensure pseudo selectors end up in final processed theme json
  • Ensure correct styles are generated for pseudo selectors from the theme json in editor.
  • Ensure correct styles are generated for pseudo selectors from the theme json on front end.
  • Consider enabling block-level elements pseudo selector support.
  • Learn how to type/spell pseudo (note: this task will never be completed)
  • Add/augment automated tests.
  • 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.
  • Augment frontend JS global styles tests to assert on pseudo selector generation.
  • Refine PR desc and make RfR

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

  • Use a Theme where you can modify the theme.json file.
  • Try adding some psudo selector styles for link element at top level:
{
    "elements": {
        "link": {
            "color": {
                "text": "green"
            },
            ":hover": {
                "color": {
                    "text": "hotpink"
                }
            }
        }
    }
}
  • validate standard a elements have a hotpink color when you hover over them on both editor and frontend.
  • now add an invalid pseudo selector and check it isn't output in the stylesheet
{
    "elements": {
        "link": {
            "color": {
                "text": "green"
            },
            ":thisisaninvalidselector": {
                "color": {
                    "text": "hotpink"
                }
            }
        }
    }
}
  • following the same pattern as above now try adding an unsupported selector such as :target.
  • following the same pattern as above now try adding an unsupported element like button.
{
    "elements": {
        "button": {
            "color": {
                "text": "green"
            },
            ":hover": {
                "color": {
                    "text": "hotpink"
                }
            }
        }
    }
}

Please be sure to check in both the Post and the Site Editor.

Screenshots or screencast

Editor

Screen Capture on 2022-06-17 at 16-00-13

Frontend

Screen Capture on 2022-06-17 at 15-57-50

Authors

Co-authored-by: Andrei Draganescu <me@andreidraganescu.info>, Adam Zielinski, Ben Dwyer <ben@scruffian.com>

@getdave getdave self-assigned this Jun 17, 2022
Comment on lines 74 to 107
// 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;
}
}
}
Copy link
Contributor Author

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.

Comment on lines 98 to 100
// 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
Copy link
Contributor Author

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 ] );
Copy link
Contributor Author

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 ) {
Copy link
Contributor Author

@getdave getdave Jun 17, 2022

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?

Copy link
Member

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?

Comment on lines 184 to 190
// 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 ] );
}
}
}
Copy link
Contributor Author

@getdave getdave Jun 17, 2022

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.

@getdave getdave added the CSS Styling Related to editor and front end styles, CSS-specific issues. label Jun 17, 2022
@draganescu draganescu added [Type] Enhancement A suggestion for improvement. Needs Technical Feedback Needs testing from a developer perspective. Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Jun 20, 2022
@getdave

This comment was marked as outdated.

lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php Outdated Show resolved Hide resolved
* @param array $input Node to process.
* @return array
*/
protected static function remove_insecure_styles( $input ) {
Copy link
Member

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?

@ramonjd
Copy link
Member

ramonjd commented Jun 21, 2022

Learn how to type/spell pseudo

When you do, can you teach me? 😄

Currently the pseudo selector rules are not being output in the Site Editor. It all works in the Post Editor and also o the front end.

This might be a long shot, but I was also having trouble with overwriting core's get_block_editor_settings() in Gutenberg

#39529 (comment)

@ramonjd
Copy link
Member

ramonjd commented Jun 21, 2022

Please note that once an element is "open" to a given pseudo selector all valid stlye properties are available to be changed.

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.

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.

If the intention is to only add color UI controls for link:hover then we have a relationship between the theme.json API and the editor: users can override link hover colors defined theme.json via global or block styles.

Would there be any benefit over regular CSS to be able to add extra styles such as typography or whatever within a :hover block in theme.json?

I suppose I'm also wondering if we should restrict/ignore styles with the exception of color within elements.link.[':hover']

@getdave

This comment was marked as outdated.

@getdave
Copy link
Contributor Author

getdave commented Jun 21, 2022

Thanks for your 👀 on this @ramonjd 🙇‍♂️

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.

Agreed - it would be limited to Theme JSON. We will only expose UI for very specific elements and pseudo selectors.

If the intention is to only add color UI controls for link:hover then we have a relationship between the theme.json API and the editor: users can override link hover colors defined theme.json via global or block styles.

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?

Would there be any benefit over regular CSS to be able to add extra styles such as typography or whatever within a :hover block in theme.json?

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 theme.json for some things and style.css for others.

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.

I suppose I'm also wondering if we should restrict/ignore styles with the exception of color within elements.link.[':hover']

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.

When you do, can you teach me? 😄

I'd have to charge 😜

Comment on lines 440 to 458
$pseudo_matches = array();
preg_match( '/:[a-z]+/', $selector, $pseudo_matches );
$pseudo_selector = $pseudo_matches[0] ?? null;
Copy link
Contributor Author

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.

Copy link
Contributor

@adamziel adamziel Jun 22, 2022

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.

Comment on lines -361 to -375
elements: {
link:
'h1 ' +
ELEMENTS.link +
',h2 ' +
ELEMENTS.link +
',h3 ' +
ELEMENTS.link +
',h4 ' +
ELEMENTS.link +
',h5 ' +
ELEMENTS.link +
',h6 ' +
ELEMENTS.link,
},
Copy link
Contributor Author

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.

Comment on lines -381 to +447
'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;}' +
Copy link
Contributor Author

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.

Copy link
Contributor

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

Comment on lines -393 to +402
if ( declarations.length === 0 ) {
return;
if ( declarations?.length ) {
ruleset = ruleset + `${ selector }{${ declarations.join( ';' ) };}`;
}
Copy link
Contributor Author

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.

@ramonjd
Copy link
Member

ramonjd commented Jun 21, 2022

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?

Yes! I just wanted to make sure I had understood things correctly 😄

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.

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 😄

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.

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 👍

pento pushed a commit to WordPress/wordpress-develop that referenced this pull request Sep 10, 2022
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
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Sep 10, 2022
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
github-actions bot pushed a commit to platformsh/wordpress-performance that referenced this pull request Sep 10, 2022
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
@mburridge mburridge added the Needs Dev Note Requires a developer note for a major WordPress release cycle label Sep 14, 2022
@mburridge
Copy link
Contributor

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.

@scruffian
Copy link
Contributor

I mentioned it in this post: https://make.wordpress.org/core/?p=98557&preview=true

@mburridge
Copy link
Contributor

Thanks @scruffian. Might it be worth adding the #dev-notes tag to that post?

@bph bph mentioned this pull request Sep 14, 2022
89 tasks
whereiscodedude pushed a commit to whereiscodedude/wpss that referenced this pull request Sep 18, 2022
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
@getdave
Copy link
Contributor Author

getdave commented Sep 20, 2022

@getdave
Copy link
Contributor Author

getdave commented Sep 22, 2022

WP 6.1 Dev note

In 6.1 support has been added to allow developers to define styles for pseudo classes (e.g. :hover, :focus) for a limited set of elements via Theme JSON.

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 elements nested within the block you wish to target:

{
    "blocks": {
        "core/group": {
             "elements": {
                "link": {
                    ":hover": {
                        "color": {
                            "text": "red"
                        }
                    }
                }
            }
        }
    }
}

In this case <a> elements within a core/group block will have red text on :hover - this results in the following CSS (actual output may vary):

.wp-block-group a:hover {
    color: red;
}

At the current time support for this feature is intentionally limited to only link (i.e. <a>) and button elements to avoid a11y and usability concerns. It may be extended in future.

ootwch pushed a commit to ootwch/wordpress-develop that referenced this pull request Nov 4, 2022
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json Needs Dev Note Requires a developer note for a major WordPress release cycle Needs Technical Feedback Needs testing from a developer perspective. [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants