Brian Kardell, Byungwoo Lee, Shwetank Dixit, and Andrea Giammarchi present at AdBlocker Dev Summit about Eyeo's sponsorship of Igalia's work in unblocking the long blocked :has pseudo-class and why it matters.
(c) AdBlocker Dev Summit 2021
https://adblockerdevsummit.com/?s=09
4. 4 directions that exist in the
relationship between two elements
<div> parent/ancestor of #refrence
<div> previous sibling of #reference </div>
<div id=reference>
<div> child/descendant of #reference </div>
</div>
<div> next sibling of #reference </div>
</div>
4
5. Combinators provide
downward directions only
<div> parent/ancestor of #refrence
<div> previous sibling of #reference </div>
<div id=reference>
<div> child/descendant of #reference <!-- #reference div -->
</div>
<div> next sibling of #reference <!-- #reference ~ div --> </d
</div>
5
6. :has() pseudo class provides
upward directions
<div> parent/ancestor of #refrence <!-- div:has(#reference) -->
<div> previous sibling of #reference <!-- div:has(~ #reference
<div id=reference>
<div> child/descendant of #reference </div>
</div>
<div> next sibling of #reference </div>
</div>
6
7. With :has(), you can use all relationships
of a reference element
7
8. <div id=div1>
<div id=div2></div>
</div>
<div id=div3>
<div id=div4>
<div id=div5></div>
</div>
<div id=reference>
<div id=div6></div>
</div>
<div id=div7>
<div id=div8></div>
</div>
</div>
<div id=div9>
<div id=div10></div>
</div>
You can match all relationships
8
12. Matching .a .b on #subject element
:has() matching is heavy operation
O(n) where n is the number of descendants
Matching .a:has(.b) on #subject element
12
13. :has() matching can be O(n²)
for the nested subjects
document.querySelectorAll('.a:has(.b)')
13
14. Changing .a for .a .b may affect downward
:has() cannot be easily integrated
with existing invalidation
Because DOM mutations affect opposite direction.
Changing .b for .a:has(.b) may affect upward
14
15. :has() can easily increase invalidation
complexity
Changing .b for .a:has(:is(b .c)) {}
15
17. Approaches?
Separations of concerns
Breaking the large/complex problems down into distinct
sections,
Getting feasible solutions for each sections,
Finding a way of combining and extending the
solutions.
17
23. Investigate approaches
Explainer & Initial Designs:
Measuring Performance:
Start prototyping in chromium.
Intent to Prototyping :
Chromium Bug :
Chrome Platform Status :
Position requests to other browser
Gecko :
WebKit :
https://github.com/Igalia/explainers/tree/main/css/has
https://css-has.glitch.me
https://groups.google.com/a/chromium.org/g/blink-dev/c/hqkcKdDrhXE
https://crbug.com/669058
https://chromestatus.com/feature/5794378545102848
https://github.com/mozilla/standards-positions/issues/528
https://www.mail-archive.com/webkit-dev@lists.webkit.org/msg30129.html
23
24. Prototyping progress (For snapshot profile)
What have done so far
Landed : Chromium (6 CLs) / WPT (3 PRs)
Support almost all :has() expressions (except related with shadow boundary crossing)
O(n²) repetitive argument matching
Propose a spec change : Remove :scope dependency from <relative selector> (
)
Need more investigations
O(n) argument matching
:has() matching with shadow boundary crossing
issue/6399
24
25. How to enable :has in snapshot profile
Enable experimental web platform features in the latest Chrome Dev (95.0.4608.0 ~)
Or pass the commandline flag CSSPseudoHasInSnapshotProfile
$ google-chrome-unstable --enable-blink-features=CSSPseudoHasInSnapshotProfile
25
26. Prototyping progress (For live profile)
Investigated (WIP)
Support invalidation for class selectors in argument : ,
Support invalidation for elemental selectors in argument :
Support invalidation for attribute selectors in argument :
Support nested :has() invalidation :
Support invalidation for :focus in argument :
Support non-terminal :has() invalidation :
Support invalidation for :has(:is()) case:
Under discussion
Clarify possible limitations to balance coverage and complexity/performance impact
Start from the maximum limitations
Support :has() at terminal top-level compound
Support :has() argument starts with child or descendant combinator
Support only one compound in :has()
Support attribute/elemental selectors in :has()
https://crrev.com/c/3067100
https://crrev.com/c/3167634
https://crrev.com/c/3067024
https://crrev.com/c/3063755
https://crrev.com/c/3066704
https://crrev.com/c/3067025
https://crrev.com/c/3067024
https://crrev/c/2893774
https://github.com/Igalia/explainers/blob/main/css/has/invalidation-discussions.md
26
27. How to enable :has in live profile
pass the commandline feature flag CSSPseudoHas
$ google-chrome-unstable --enable-blink-features=CSSPseudoHas
27
28. This is what currently under discussion in
live profile
28
30. Plans for the remaining tasks
~ 2021.Q4
Initial :has() invalidation
Support :has() at terminal top-level compound
Support :has() argument starts with child or descendant combinator
Support only one compound in :has()
Support attribute/elemental selectors in :has()
Not yet planned
:has() in live profile
Support complex selector in :has()
Support selector list in :has()
Support non-terminal :has()
Support :has() in logical combinations
Support :has() argument starts with ~ or +
Support pseudos in :has()
:has() in snapshot profile
O(n) argument matching overhead
:has() matching with shadow boundary crossing
:has() in other browsers ( :has seems to be in WebKit Radar 2022)
30