Global styles: Simplify CSS processing#76078
Conversation
|
Size Change: -497 B (-0.01%) Total Size: 6.87 MB
ℹ️ View Unchanged
|
|
@ramonjd @aaronrobertshaw @andrewserong I believe you folks have some experience with this system. Does this direction seem viable? Was there a reason that CSS nesting is avoided instead of allowing it to happen? |
|
I went back to @t-hamano's original implementation of By the way, I went through the test steps of that PR on this branch and things look good! Then pseudo element selectors came into the bag. @aaronrobertshaw's PR addressed malformed selectors. I also went through those test steps on this branch and it LGTM
That's where my knowledge of the history runs dry, though, if you tied me up and threatened my goldfish for an answer, I'd guess that it was also because CSS Nesting was fairly new back in the day (2023) and maybe it couldn't be relied upon. Also, and I'm guessing, there's no CSSStyleSheet equivalent in PHP, so the parsing logic had to remain the same? I'm looking at process_blocks_custom_css That said, you mentioned there are possibilities to use |
| try { | ||
| return ss.cssRules[ | ||
| ss.insertRule( `:root :where(${ blockSelector }){${ css }}` ) | ||
| ].cssText; |
There was a problem hiding this comment.
I read somewhere that some browsers don't normalize the output of cssText in the same way. I ran a few nested selectors through FF, Safari and Chrome and it looked okay to me. Just saying.
There was a problem hiding this comment.
Oh, I might have confused it with CSSStyleDeclaration.cssText
There was a problem hiding this comment.
I was thinking about validation more than normalization here. insertRule should throw if you do something like give it invalid syntax or multiple rules, which seems like a good safeguard against things that we don't want to support like } body { visibility: hidden;
Oh yeah, &::before { content: 'Foo' };
border-width: 1px;
border-style:solid; border-color:black;
|
Right, this only explores the in-editor side of things. Presumably, in PHP we need something similar. This is another case where we need to deal with CSS. Assumptions and regular expressions are limiting and insufficient. Ticket 63568 is a good example of this, which only needs to deal with CSS strings and identifiers. That's why I suggest:
Ultimately, I think that's the answer. There are many places around Core that would benefit from CSS parsing/processing and this is just one more example. |
I made a typo here, I meant to say
Yeah it seems this is coming up more and more. Thank you for donning this t-shirt by the way and getting sweaty with the problem. |
|
There's a problem with this method in the browser. Repeated style declarations are collapsed into whichever one the browser uses, making this a lossy approach. CSS has two design choices that are relevant here:
When authoring CSS that allows for progressive enhancement. Well-supported features are used as a baseline, and more modern features are used when available. The web APIs like For example, consider the CSS in this snippet of HTML: <style>
li {
color: rebeccapurple;
color: oklch( from rebeccapurple L C calc( H * sibling-index() ) );
}
</style>
<ol><li><li><li><li><li><li>The
Unfortunately, this browser's support is reflected in the const ss = new CSSStyleSheet();
const css = ss.cssRules[ ss.insertRule( `li {
color: rebeccapurple;
color: oklch( from rebeccapurple L C calc( H * sibling-index() ) );
}` ) ].cssText;And here are the values of
The intentional duplicate declaration and progressive enhancement is lost. The result is either the basic version or the enhanced version, neither of which is the desirable result. It may be viable to use |
The resulting rule is parsed by the browser, discarding repeated declarations that may be desirable for progressive enhancement.
There was a problem hiding this comment.
Pull request overview
This PR explores simplifying how the global styles engine handles nested custom CSS by replacing manual string/regex processing with native CSS parsing (via CSSOM) for basic correctness validation and output.
Changes:
- Removes the bespoke
&-based splitting/selector-rewriting logic fromprocessCSSNesting. - Attempts to validate user-provided CSS by inserting a constructed rule into a
CSSStyleSheetand returning the resulting rule text (or''on failure).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const ss = new CSSStyleSheet(); | ||
| try { | ||
| return ss.cssRules[ | ||
| ss.insertRule( `:root :where(${ blockSelector }){${ css }}` ) | ||
| try { | ||
| const cssRuleText = `:root :where(${ blockSelector }){${ css }}`; | ||
| new CSSStyleSheet().insertRule( cssRuleText, 0 ); |
| const ss = new CSSStyleSheet(); | ||
| try { | ||
| return ss.cssRules[ | ||
| ss.insertRule( `:root :where(${ blockSelector }){${ css }}` ) | ||
| try { | ||
| const cssRuleText = `:root :where(${ blockSelector }){${ css }}`; | ||
| new CSSStyleSheet().insertRule( cssRuleText, 0 ); | ||
| return cssRuleText; | ||
| } catch { | ||
| return ''; |
| const ss = new CSSStyleSheet(); | ||
| try { | ||
| return ss.cssRules[ | ||
| ss.insertRule( `:root :where(${ blockSelector }){${ css }}` ) | ||
| try { |





WIP exploration
What?
Simplify JavaScript processing of nested CSS rules. Allow the rules to nest with simple correctness checking via built-in APIs.
PHP would need to be updated accordingly. A PHP-based CSS parser will likely become necessary. There is some prior art for this. A PR contains CSS selector parsing, and the php-toolkit contains a CSSProcessor class.
Input
Before
After
Why?
The existing system relies on regular expressions, and checking for the presence of and splitting on CSS syntax. However, the characters used in
{}and&may be used in other ways in CSS.This also relaxes the requirement to use
& .descendent {}instead of simply nesting.descendent {}which should also work fine.How?
Testing Instructions
Testing Instructions for Keyboard
Screenshots or screencast