Make WordPress Core


Ignore:
Timestamp:
07/27/2026 04:09:33 AM (4 weeks ago)
Author:
ramonopoly
Message:

Theme JSON: Level block-level preset class specificity with :where()

Block-level preset classes are now wrapped in :where() so they keep the same 0-1-0 specificity as root-level preset classes.

A palette defined at block level (via the wp_theme_json_data_theme filter or settings.blocks) emits p.has-x-color at 0-1-1 specificity, while a root-level palette emits .has-x-color at 0-1-0. Responsive style states emit their rules at 0-1-0. Both use !important, so specificity decides the winner: the block-level preset out-ranks the state rule, and a Desktop palette colour overrides the Mobile colour at every viewport width.

Wrapping the block selector in :where() contributes zero specificity while keeping the same scoping, so the preset ties the state rule and loses on source order, matching root-level behaviour. Palette values are unaffected because they flow through the scoped --wp--preset--color--* variable, not the class.

Developed in: https://github.com/WordPress/wordpress-develop/pull/12705(https://github.com/WordPress/wordpress-develop/pull/12705)

Props awetz583, ramonopoly, andrewserong.

Fixes #65724.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r62746 r62853  
    806806         * @ticket 52991
    807807         * @ticket 54336
     808         * @ticket 65724
    808809         */
    809810        public function test_get_stylesheet_preset_classes_work_with_compounded_selectors() {
     
    829830
    830831                $this->assertSame(
    831                         '.wp-block-heading.has-white-color{color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.wp-block-heading.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}',
     832                        ':where(.wp-block-heading).has-white-color{color: var(--wp--preset--color--white) !important;}:where(.wp-block-heading).has-white-background-color{background-color: var(--wp--preset--color--white) !important;}:where(.wp-block-heading).has-white-border-color{border-color: var(--wp--preset--color--white) !important;}',
    832833                        $theme_json->get_stylesheet( array( 'presets' ) )
    833834                );
     
    895896         * @ticket 60936
    896897         * @ticket 61165
     898         * @ticket 65724
    897899         */
    898900        public function test_get_stylesheet_preset_rules_come_after_block_rules() {
     
    927929
    928930                $styles    = ':root :where(.wp-block-group){color: red;}';
    929                 $presets   = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}';
     931                $presets   = ':where(.wp-block-group).has-grey-color{color: var(--wp--preset--color--grey) !important;}:where(.wp-block-group).has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}:where(.wp-block-group).has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}';
    930932                $variables = '.wp-block-group{--wp--preset--color--grey: grey;}';
    931933
Note: See TracChangeset for help on using the changeset viewer.