Skip to content

Commit 3dc574b

Browse files
ellatrixaaronrobertshawtellthemachinestalldanandrewserong
authored andcommitted
Styles: Level specificity using :root to fix reset styles (WordPress#61638)
Co-authored-by: ellatrix <[email protected]> Co-authored-by: aaronrobertshaw <[email protected]> Co-authored-by: tellthemachines <[email protected]> Co-authored-by: talldan <[email protected]> Co-authored-by: andrewserong <[email protected]> Co-authored-by: kevin940726 <[email protected]>
1 parent 89c256e commit 3dc574b

File tree

35 files changed

+401
-384
lines changed

35 files changed

+401
-384
lines changed

backport-changelog/6.6/6522.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
https://github.com/WordPress/wordpress-develop/pull/6522
2+
3+
* https://github.com/WordPress/gutenberg/pull/60106
4+
* https://github.com/WordPress/gutenberg/pull/60228
5+
* https://github.com/WordPress/gutenberg/pull/61638

lib/class-wp-theme-json-gutenberg.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ protected function process_blocks_custom_css( $css, $selector ) {
12931293
$is_root_css = ( ! str_contains( $part, '{' ) );
12941294
if ( $is_root_css ) {
12951295
// If the part doesn't contain braces, it applies to the root level.
1296-
$processed_css .= trim( $selector ) . '{' . trim( $part ) . '}';
1296+
$processed_css .= ':root :where(' . trim( $selector ) . '){' . trim( $part ) . '}';
12971297
} else {
12981298
// If the part contains braces, it's a nested CSS rule.
12991299
$part = explode( '{', str_replace( '}', '', $part ) );
@@ -1305,7 +1305,8 @@ protected function process_blocks_custom_css( $css, $selector ) {
13051305
$part_selector = str_starts_with( $nested_selector, ' ' )
13061306
? static::scope_selector( $selector, $nested_selector )
13071307
: static::append_to_selector( $selector, $nested_selector );
1308-
$processed_css .= $part_selector . '{' . trim( $css_value ) . '}';
1308+
$final_selector = ":root :where($part_selector)";
1309+
$processed_css .= $final_selector . '{' . trim( $css_value ) . '}';
13091310
}
13101311
}
13111312
return $processed_css;
@@ -1322,6 +1323,7 @@ public function get_custom_css() {
13221323
$block_custom_css = '';
13231324
$block_nodes = $this->get_block_custom_css_nodes();
13241325
foreach ( $block_nodes as $node ) {
1326+
// The node selector will have its specificity set to 0-1-0 within process_blocks_custom_css.
13251327
$block_custom_css .= $this->get_block_custom_css( $node['css'], $node['selector'] );
13261328
}
13271329

@@ -1564,7 +1566,7 @@ protected function get_layout_styles( $block_metadata, $types = array() ) {
15641566
$spacing_rule['selector']
15651567
);
15661568
} else {
1567-
$format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s) %3$s' : ':where(%1$s-%2$s) %3$s';
1569+
$format = static::ROOT_BLOCK_SELECTOR === $selector ? '.%2$s %3$s' : '%1$s-%2$s %3$s';
15681570
$layout_selector = sprintf(
15691571
$format,
15701572
$selector,
@@ -2745,7 +2747,7 @@ static function ( $pseudo_selector ) use ( $selector ) {
27452747
}
27462748

27472749
// 2. Generate and append the rules that use the general selector.
2748-
$block_rules .= static::to_ruleset( ":where($selector)", $declarations );
2750+
$block_rules .= static::to_ruleset( ":root :where($selector)", $declarations );
27492751

27502752
// 3. Generate and append the rules that use the duotone selector.
27512753
if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) {
@@ -2762,12 +2764,12 @@ static function ( $pseudo_selector ) use ( $selector ) {
27622764

27632765
// 5. Generate and append the feature level rulesets.
27642766
foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) {
2765-
$block_rules .= static::to_ruleset( ":where($feature_selector)", $individual_feature_declarations );
2767+
$block_rules .= static::to_ruleset( ":root :where($feature_selector)", $individual_feature_declarations );
27662768
}
27672769

27682770
// 6. Generate and append the style variation rulesets.
27692771
foreach ( $style_variation_declarations as $style_variation_selector => $individual_style_variation_declarations ) {
2770-
$block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations );
2772+
$block_rules .= static::to_ruleset( ":root :where($style_variation_selector)", $individual_style_variation_declarations );
27712773
}
27722774

27732775
return $block_rules;

lib/theme.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,40 @@
370370
"bottom": "0px",
371371
"left": "0px"
372372
}
373+
},
374+
"blocks": {
375+
"core/button": {
376+
"variations": {
377+
"outline": {
378+
"border": {
379+
"width": "2px",
380+
"style": "solid",
381+
"color": "currentColor"
382+
},
383+
"color": {
384+
"text": "currentColor",
385+
"gradient": "transparent none"
386+
},
387+
"spacing": {
388+
"padding": {
389+
"top": "0.667em",
390+
"right": "1.33em",
391+
"bottom": "0.667em",
392+
"left": "1.33em"
393+
}
394+
}
395+
}
396+
}
397+
},
398+
"core/site-logo": {
399+
"variations": {
400+
"rounded": {
401+
"border": {
402+
"radius": "9999px"
403+
}
404+
}
405+
}
406+
}
373407
}
374408
}
375409
}

packages/block-editor/src/components/global-styles/test/use-global-styles-output.js

Lines changed: 11 additions & 10 deletions
Large diffs are not rendered by default.

packages/block-editor/src/components/global-styles/use-global-styles-output.js

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,10 @@ export function getLayoutStyles( {
522522
} else {
523523
combinedSelector =
524524
selector === ROOT_BLOCK_SELECTOR
525-
? `:where(.${ className })${
525+
? `.${ className }${
526526
spacingStyle?.selector || ''
527527
}`
528-
: `:where(${ selector }-${ className })${
528+
: `${ selector }-${ className }${
529529
spacingStyle?.selector || ''
530530
}`;
531531
}
@@ -860,12 +860,56 @@ export const toStyles = (
860860
( [ cssSelector, declarations ] ) => {
861861
if ( declarations.length ) {
862862
const rules = declarations.join( ';' );
863-
ruleset += `:where(${ cssSelector }){${ rules };}`;
863+
ruleset += `:root :where(${ cssSelector }){${ rules };}`;
864864
}
865865
}
866866
);
867867
}
868868

869+
// Process duotone styles.
870+
if ( duotoneSelector ) {
871+
const duotoneStyles = {};
872+
if ( styles?.filter ) {
873+
duotoneStyles.filter = styles.filter;
874+
delete styles.filter;
875+
}
876+
const duotoneDeclarations =
877+
getStylesDeclarations( duotoneStyles );
878+
if ( duotoneDeclarations.length ) {
879+
ruleset += `${ duotoneSelector }{${ duotoneDeclarations.join(
880+
';'
881+
) };}`;
882+
}
883+
}
884+
885+
// Process blockGap and layout styles.
886+
if (
887+
! disableLayoutStyles &&
888+
( ROOT_BLOCK_SELECTOR === selector || hasLayoutSupport )
889+
) {
890+
ruleset += getLayoutStyles( {
891+
style: styles,
892+
selector,
893+
hasBlockGapSupport,
894+
hasFallbackGapSupport,
895+
fallbackGapValue,
896+
} );
897+
}
898+
899+
// Process the remaining block styles (they use either normal block class or __experimentalSelector).
900+
const styleDeclarations = getStylesDeclarations(
901+
styles,
902+
selector,
903+
useRootPaddingAlign,
904+
tree,
905+
disableRootPadding
906+
);
907+
if ( styleDeclarations?.length ) {
908+
ruleset += `:root :where(${ selector }){${ styleDeclarations.join(
909+
';'
910+
) };}`;
911+
}
912+
869913
if ( styleVariationSelectors ) {
870914
Object.entries( styleVariationSelectors ).forEach(
871915
( [ styleVariationName, styleVariationSelector ] ) => {
@@ -892,7 +936,7 @@ export const toStyles = (
892936
);
893937
const rules =
894938
declarations.join( ';' );
895-
ruleset += `${ cssSelector }{${ rules };}`;
939+
ruleset += `:root :where(${ cssSelector }){${ rules };}`;
896940
}
897941
}
898942
);
@@ -907,7 +951,7 @@ export const toStyles = (
907951
tree
908952
);
909953
if ( styleVariationDeclarations.length ) {
910-
ruleset += `${ styleVariationSelector }{${ styleVariationDeclarations.join(
954+
ruleset += `:root :where(${ styleVariationSelector }){${ styleVariationDeclarations.join(
911955
';'
912956
) };}`;
913957
}
@@ -916,50 +960,6 @@ export const toStyles = (
916960
);
917961
}
918962

919-
// Process duotone styles.
920-
if ( duotoneSelector ) {
921-
const duotoneStyles = {};
922-
if ( styles?.filter ) {
923-
duotoneStyles.filter = styles.filter;
924-
delete styles.filter;
925-
}
926-
const duotoneDeclarations =
927-
getStylesDeclarations( duotoneStyles );
928-
if ( duotoneDeclarations.length ) {
929-
ruleset += `${ duotoneSelector }{${ duotoneDeclarations.join(
930-
';'
931-
) };}`;
932-
}
933-
}
934-
935-
// Process blockGap and layout styles.
936-
if (
937-
! disableLayoutStyles &&
938-
( ROOT_BLOCK_SELECTOR === selector || hasLayoutSupport )
939-
) {
940-
ruleset += getLayoutStyles( {
941-
style: styles,
942-
selector,
943-
hasBlockGapSupport,
944-
hasFallbackGapSupport,
945-
fallbackGapValue,
946-
} );
947-
}
948-
949-
// Process the remaining block styles (they use either normal block class or __experimentalSelector).
950-
const declarations = getStylesDeclarations(
951-
styles,
952-
selector,
953-
useRootPaddingAlign,
954-
tree,
955-
disableRootPadding
956-
);
957-
if ( declarations?.length ) {
958-
ruleset += `:where(${ selector }){${ declarations.join(
959-
';'
960-
) };}`;
961-
}
962-
963963
// Check for pseudo selector in `styles` and handle separately.
964964
const pseudoSelectorStyles = Object.entries( styles ).filter(
965965
( [ key ] ) => key.startsWith( ':' )
@@ -1018,13 +1018,13 @@ export const toStyles = (
10181018
getGapCSSValue( tree?.styles?.spacing?.blockGap ) || '0.5em';
10191019
ruleset =
10201020
ruleset +
1021-
`:where(.wp-site-blocks) > * { margin-block-start: ${ gapValue }; margin-block-end: 0; }`;
1021+
`:root :where(.wp-site-blocks) > * { margin-block-start: ${ gapValue }; margin-block-end: 0; }`;
10221022
ruleset =
10231023
ruleset +
1024-
':where(.wp-site-blocks) > :first-child { margin-block-start: 0; }';
1024+
':root :where(.wp-site-blocks) > :first-child { margin-block-start: 0; }';
10251025
ruleset =
10261026
ruleset +
1027-
':where(.wp-site-blocks) > :last-child { margin-block-end: 0; }';
1027+
':root :where(.wp-site-blocks) > :last-child { margin-block-end: 0; }';
10281028
}
10291029

10301030
if ( options.presets ) {
@@ -1185,7 +1185,7 @@ export function processCSSNesting( css, blockSelector ) {
11851185
const isRootCss = ! part.includes( '{' );
11861186
if ( isRootCss ) {
11871187
// If the part doesn't contain braces, it applies to the root level.
1188-
processedCSS += `${ blockSelector }{${ part.trim() }}`;
1188+
processedCSS += `:root :where(${ blockSelector }){${ part.trim() }}`;
11891189
} else {
11901190
// If the part contains braces, it's a nested CSS rule.
11911191
const splittedPart = part.replace( '}', '' ).split( '{' );
@@ -1198,7 +1198,7 @@ export function processCSSNesting( css, blockSelector ) {
11981198
? scopeSelector( blockSelector, nestedSelector )
11991199
: appendToSelector( blockSelector, nestedSelector );
12001200

1201-
processedCSS += `${ combinedSelector }{${ cssValue.trim() }}`;
1201+
processedCSS += `:root :where(${ combinedSelector }){${ cssValue.trim() }}`;
12021202
}
12031203
} );
12041204
return processedCSS;

packages/block-library/src/audio/theme.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
@include caption-style-theme();
33
}
44

5-
:where(.wp-block-audio) {
5+
.wp-block-audio {
66
margin: 0 0 1em 0;
77
}

packages/block-library/src/button/editor.scss

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,3 @@ div[data-type="core/button"] {
3737
text-decoration: inherit;
3838
}
3939

40-
.editor-styles-wrapper .wp-block-button .wp-block-button__link {
41-
// The following styles ensure a default border is applied when the user selects only a border color or style in the editor,
42-
// but no width. They override the `border-width: 0;` applied by core's theme.json via the Elements API button.
43-
&:where(.has-border-color) {
44-
border-width: initial;
45-
}
46-
&:where([style*="border-top-color"]) {
47-
border-top-width: initial;
48-
}
49-
&:where([style*="border-right-color"]) {
50-
border-right-width: initial;
51-
}
52-
&:where([style*="border-bottom-color"]) {
53-
border-bottom-width: initial;
54-
}
55-
&:where([style*="border-left-color"]) {
56-
border-left-width: initial;
57-
}
58-
59-
&:where([style*="border-style"]) {
60-
border-width: initial;
61-
}
62-
&:where([style*="border-top-style"]) {
63-
border-top-width: initial;
64-
}
65-
&:where([style*="border-right-style"]) {
66-
border-right-width: initial;
67-
}
68-
&:where([style*="border-bottom-style"]) {
69-
border-bottom-width: initial;
70-
}
71-
&:where([style*="border-left-style"]) {
72-
border-left-width: initial;
73-
}
74-
}

0 commit comments

Comments
 (0)