Skip to content

[cssom-1] Expose resolved selectorText on CSSStyleRule #10246

Open

Description

@bramus

On a CSSStyleRule you can get the selectorText that returns the textual representation of the selector.

With CSS nesting, this value has become somewhat less useful as it doesn’t represent the full selector.

While an author can use script to compute the flattened selector by manually walking the .parentRule to the top and then doing the checks + replacements for &, it would be nice if this was built into the platform. That way, an author can directly use it in something like document.querySelectorAll.

I’m thinking of a property named flattenedSelectorText or fullSelectorText.

Activity

  1. romainmenke commented on Apr 24, 2024

    @romainmenke
    Member

    This would be very useful!

    For all things PostCSS, Stylelint, ... we also need to determine the full selector and I created a helper for this : https://github.com/csstools/postcss-plugins/tree/main/packages/selector-resolve-nested#readme

    The wording we use is a bit different : https://github.com/csstools/postcss-plugins/blob/main/packages/selector-resolve-nested/docs/selector-resolve-nested.md#functions

    We use flatten for naive replacements. This does a simple replacement of & with the parent selector. The result is a mangled selector that won't match the same elements but this is useful for static analysis. (e.g. how many type selectors did the author write in source?)

    We use resolve to get a full selector that would also match the same elements. (e.g. what is the specificity of this selector?)

    If there was a specification for this action we should have similar behavior between tooling and browsers.

  2. bramus commented on Apr 24, 2024

    @bramus
    ContributorAuthor

    Great distinction between flattened and resolved. Given this, what I suggested would better be named resolvedSelectorText.

  3. Loirooriol commented on Apr 24, 2024

    @Loirooriol
    Contributor

    This seems vulnerable to a "billion laughs attack".

  4. romainmenke commented on Apr 24, 2024

    @romainmenke
    Member

    It is, but given that it is a script API it could have limits and throw when those limits are exceeded.

    Edit : It is not.
    This would serialize selectors with :is()

  5. Loirooriol commented on Apr 24, 2024

    @Loirooriol
    Contributor

    it could have limits and throw when those limits are exceeded

    This seems very fragile. I would prefer a different design that doesn't suffer from this, e.g.

    document.querySelectorAllWithNesting("a, b", "& c, & d", "& e, & f")

    instead of

    document.querySelectorAll("a c e, a c f, a d e, a d f, b c e, b c f, b d e, b d f")
    document.querySelectorAll(":is(:is(a, b) c, :is(a, b) d) e, :is(:is(a, b) c, :is(a, b) d) f")

    This would serialize selectors with :is()

    This doesn't avoid the problem.

  6. romainmenke commented on Apr 24, 2024

    @romainmenke
    Member

    You are right, it makes it slightly smaller.

    But still quickly explodes in cases like this one :

    a,
    b {
    	&+&,
    	&>& {
    		&+&,
    		&>& {
    			color: green;
    		}
    	}
    }
  7. tabatkins commented on Apr 25, 2024

    @tabatkins
    Member

    The current OM does represent the full selector; the & selector is not evaluated by substitution, but rather refers directly to the elements selected by the parent rule.

    Understanding the use-cases better would be useful. If it's about making it easier to select the same elements in qSA() as a particular style block, we can cater to that more directly. @Loirooriol's suggestion (multiple selector arguments, representing nested selectors) might work, for example. But also, you seem to be suggesting that authors would be willing to crawl the OM and obtain a selector directly off of the CSSStyleRule - how serious were you about that in particular as a use-case? Because we could also, say, allow qSA() to take a CSSStyleRule directly, and return the same set of elements the rule matches, if that code pattern seems realistic.

    Romain mentions some preprocessor uses, notably determining the specificity. Is there more?

  8. romainmenke commented on Apr 25, 2024

    @romainmenke
    Member

    preprocessor uses, notably determining the specificity. Is there more?

    For preprocessors or author tooling in general? No, all variations on the same theme :)

    e.g. determining if &::before {} would be valid, which it might not be if & represents something like ::after. This is essentially the same problem as calculating specificity.

    You need to do something with & to be able to give feedback on what the author wrote.
    This is true for any indirection (e.g. var())

  9. bramus commented on Apr 25, 2024

    @bramus
    ContributorAuthor

    The current OM does represent the full selector; the & selector is not evaluated by substitution, but rather refers directly to the elements selected by the parent rule.

    Sorry, should have said “flattened” or “resolved” selector.

    Understanding the use-cases better would be useful. If it's about making it easier to select the same elements in qSA() as a particular style block, we can cater to that more directly.

    That’s my specific use-case indeed.

    You seem to be suggesting that authors would be willing to crawl the OM and obtain a selector directly off of the CSSStyleRule - how serious were you about that in particular as a use-case?

    It came up when writing a (rough) polyfill for ident() + attr() for this demo but admittedly not all authors write that type of stuff.

    Another use case is doing an analysis of the loaded CSS (nesting depth, layers extraction, etc.) with userland code.

  10. LeaVerou commented on Apr 25, 2024

    @LeaVerou
    Member

    Agree that the OM needs to provide both. If selectorText produces the full/resolved selector, then localSelector could produce the local one.

  11. Loirooriol commented on Apr 25, 2024

    @Loirooriol
    Contributor

    @LeaVerou I'm confused, isn't the current selector the same as the local one?

  12. LeaVerou commented on Apr 25, 2024

    @LeaVerou
    Member
  13. bramus commented on Apr 26, 2024

    @bramus
    ContributorAuthor

    @LeaVerou You still got it flipped, no?

    selectorText is the existing property which returns the local selector. The ask in c0 is for a new property that returns the resolved selector.

  14. changed the title [-][cssom-1] Expose nested selectorText on CSSStyleRule[/-] [+][cssom-1] Expose resolved selectorText on CSSStyleRule[/+] on Oct 1, 2024
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