Skip to content

Element.matches and pseudo-elements #185

Closed as not planned
Closed as not planned

Description

@SimonSapin

https://dom.spec.whatwg.org/#dom-element-matches links to https://drafts.csswg.org/selectors-4/#match-a-selector-against-an-element which links to https://drafts.csswg.org/selectors-4/#evaluate-a-selector which says:

APIs using this algorithm […] may optionally provide […] which pseudo-elements are allowed to show up in the match list, if any. If not specified, this defaults to allowing all pseudo-elements.

As far as I understand, "allowing all pseudo-elements" means that pseudo-elements are effectively ignored during matching. For example, document.body.matches('body::after') should return true. This seems backwards, and indeed Firefox 44 and Chromium 49 both return false.

The DOM spec should probably add “with an empty list of pseudo-elements” near “the result of match a selector against an element”.

Other Selectors-related APIs likely have similar issues.

Activity

  1. annevk commented on Mar 5, 2016

    @annevk
    Member

    I don't really understand the setup here. @tabatkins how can CSS just return a pseudo-element? The engine needs to have the context of a node or a set of nodes, no?

  2. tabatkins commented on Mar 7, 2016

    @tabatkins
    Contributor

    The prose algorithm can return pseudos, because the result might be used by further prose algorithms that understand pseudo-elements.

    Obviously there's not currently any way to surface pseudo-elements in JS.

  3. annevk commented on Mar 8, 2016

    @annevk
    Member

    Don't you need to have a node and a pseudo? It seems like you're assuming the node tree and the layout tree are intertwined, which would be weird.

  4. annevk commented on Aug 17, 2016

    @annevk
    Member
  5. tabatkins commented on Aug 17, 2016

    @tabatkins
    Contributor

    Augh, I didn't pay enough attention to the OP here anyway.

    Wrt the OP, document.body.matches('body::after') definitely returns false as currently specified. "Evaluate the selector" ends up returning just the body's ::after pseudo-element, and then "match the selector against an element" doesn't find <body> in the list, so you get false, as expected. So, DOM doesn't need to do anything here.

    querySelector() does need to pass an empty list of allowed pseudo-elements, tho, since otherwise you get nonsensical results (there's no way to reflect a pseudo-element as a JS object right now).

  6. annevk commented on Aug 17, 2016

    @annevk
    Member

    How can it return a pseudo-element though? Does that carry a pointer to the element?

  7. tabatkins commented on Aug 17, 2016

    @tabatkins
    Contributor

    Yes, pseudo-elements (the spec concept) have a pointer to their originating element. If/when we expose pseudo-elements to JS, they'll similarly have a parentElement attribute.

  8. annevk commented on Aug 17, 2016

    @annevk
    Member

    Thanks, and the pseudo-element gets returned because the selector was parsed successfully and it is the last thing in the list? No out-of-band information involved?

  9. tabatkins commented on Aug 17, 2016

    @tabatkins
    Contributor

    Your first question confuses me a little bit - the pseudo-element gets returned because that's what the selector selects. Unclear what out-of-band information you could be talking about.

  10. annevk commented on Aug 17, 2016

    @annevk
    Member

    I'm wondering if we're on the same page that the input to the algorithm is the selector and the node tree only.

  11. tabatkins commented on Aug 17, 2016

    @tabatkins
    Contributor

    Yes, that's it. But the output isn't restricted to things from the node tree (it's nodes + pseudo-elements).

  12. annevk commented on Aug 18, 2016

    @annevk
    Member

    I still don't understand why it would default to allowing all pseudo-elements. This algorithm is specifically designed for querySelector() and matches(). Why make the invocation more complicated?

    Does it have any invocations other than those two APIs?

  13. annevk commented on Mar 16, 2017

    @annevk
    Member
  14. annevk commented on Jul 9, 2026

    @annevk
    Member

    @tabatkins thoughts?

  15. tabatkins commented on Jul 13, 2026

    @tabatkins
    Contributor

    lol whoops, what a ping.

    Looks like this was fixed back in 2017. The algo was rewritten to no longer talk about pseudo-elements at all, so calling it with the selector body::after will just fail to return any matches.

    As HTML is still calling the algorithm correctly, we can go ahead and close this.

  16. annevk commented on Jul 14, 2026

    @annevk
    Member

    Thanks!

  17. cdoublev commented on Jul 20, 2026

    @cdoublev

    I am confused.

    My understanding is that you are referring to the rewrite of match a selector against a tree. The new version, which is still the same version today, do talk about pseudo-elements:

    1. For each possible pseudo-element associated with element that is one of the pseudo-elements allowed to show up in the match list, if the result of match a selector against a pseudo-element for the pseudo-element and selector is success, add the pseudo-element to the selector match list.
  18. tabatkins commented on Jul 20, 2026

    @tabatkins
    Contributor

    No, I'm referring to https://dom.spec.whatwg.org/#dom-element-matches, which calls "match a selector against an element".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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