Skip to content

[selectors-4] Consider disallowing :scope inside :has() #7211

Closed
@byung-woo

Description

@byung-woo

:scope inside :has() is related to these two issues:

  • Consider removing the :scope dependency from the relative selectors definition (issue 6399)
  • Consider disallowing the logical combinations pseudo classes inside :has() (issue 6952)

According to the current definition of absolutizing a relative selector using :scope, these 3 selectors are identical.

  • .b:has(.a :scope .c)
  • .b:has(:is(.a :scope) .c)
  • .a .b:has(.c)

As pointed at the previous issues (issue 6399, issue 6952),

  1. :is() inside :has() increases invalidation complexity,
  2. the compound selector in the left side of the :scope inside :has() creates exactly same problem that :is() inside :has() creates,
  3. we don't need to use :scope inside :has() because there can be much simpler expression.

So, it would be better not to use :scope inside :has() when we follow the current spec of absolutizing relative selectors.

Even if we follow the suggestion of (issue 6399), :scope inside :has() will work only when we use it in the snapshot profile.

  • In the style rule, :scope inside :has() will not match any element because any subject element of :has() pseudo class cannot have the root as its descendant or next sibling. (The only possible way is to use :scope with :is() like .a:has(~ :is(:scope > .b) .c))

In the snapshot profile, :scope inside subject :has() will not match any element when we call querySelector(), querySelectorAll(), matches() because the :scope element of the node selector API method call cannot be a descendant or next sibling of the :scope element itself or its descendants. Same with above, the only possible way is to use it with :is().

So, if :is() is disallowed inside :has(), the :scope inside :has() will work only in these usages, but I'm not sure that this is useful in practice.

  • call closest() with a selector using :scope inside subject :has()
    • element.closest(".a:has(:scope ~ .b)")
  • call node selector APIs with a selector using :scope inside non-subject :has()
    • element.querySelectorAll(".a:has(:scope ~ .b) .c")
    • element.querySelector(".a:has(:scope ~ .b) .c")
    • element.matches(".a:has(:scope ~ .b) .c")
    • element.closest(".a:has(:scope ~ .b) .c")

How about avoiding this confusion by disallowing :scope inside :has()?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions