Editor: Stop :has() selectors recalculating the whole document on every block selection - #81471
Editor: Stop :has() selectors recalculating the whole document on every block selection#81471Mamaduka wants to merge 1 commit into
:has() selectors recalculating the whole document on every block selection#81471Conversation
…very block selection
|
Size Change: +80 B (0%) Total Size: 7.71 MB 📦 View Changed
|
I think we should remove this throwaway case, as it can mask an actual regression. For example, the editable root change (removed in #81184) affected the first selection significantly, but switching between blocks was cheaper. So, as a user opening a large post, the first selection was junky, but this was missed by our specs. The downside is that our metrics will probably jump, but they'll show numbers close to the actual median. cc @ellatrix, @youknowriad, @tyxla |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |


What?
Related #81457.
Rewrites four
:has()rules in the editor and interface styles so that each:has()compound is the subject of its own rule.Why?
Clicking a paragraph in a 1000-paragraph post ran about 8 full document-style recalcs in the
post.phpframe. The cause isbody:has(.editor-editor-interface.is-distraction-free) #wpadminbar { display: none }. Blink treats a:has()whose subject sits below the anchor differently from one where the anchor is the subject: it cannot tell which descendants are affected, so it flags the anchor's entire subtree and recalculates it on every DOM change during the React commit. The same pattern appeared in the revisions timeline and the collab sidebar rules.Splitting the distraction-free rule in two confirmed where the cost was. The inherited custom property half is free, and the
#wpadminbarhalf accounts for all of it.How?
The distraction-free state now reaches the admin bar through a second inherited custom property, so
bodystays the subject of its own:has(). The revisions timeline rules are unnested, since their subjects exist only in revisions mode and do not require the extra scoping. The collab sidebar header is targeted by its own class instead of a:has()on the skeleton sidebar.Results
Measured across two real builds with the arms alternating within one session, since sequential A/B blocks are not reliable at this size.
Selecting blocksperf metric (median of 40 clicks)BODYsubtree invalidations per clickThe document has 792 elements, so the whole document recalcs are gone.
The
Selecting blocksmetric discards the first click, so it reports the steady state improvement of about 17 percent rather than the larger first click one. Head won all four rounds with no overlap between the per-round ranges.Testing Instructions
Some of these have e2e test coverage, so the smoke test affected features:
Testing Instructions for Keyboard
Same.
Use of AI Tools
Assisted by Claude