Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[selectors-4] Attribute match syntax extended to cover tag selectors #6571

Open
castastrophe opened this issue Sep 2, 2021 · 11 comments
Open
Labels

Comments

@castastrophe
Copy link

castastrophe commented Sep 2, 2021

Link: https://www.w3.org/TR/2018/WD-selectors-4-20181121/

With the advent of custom elements and the growing popularity of web component libraries (especially those with common prefixes), the need for a way to target a tag selector using attribute match syntax has increased.

Use case

I have library x with a set of components: x-foo, x-bar, x-bat. I want to write styles influence only those components on the page but I'm not sure which components are in use.

Suggestions

In this thread, a few ideas were proposed: https://twitter.com/castastrophee/status/1433418836364210182?s=20

I'll do my best to summarize:

  1. Add support for wildcard syntax with selectors, i.e. x-* { color: red; }.
  2. Add support for wildcard syntax inside the :is() pseudo-selector i.e. :is(x-*)
  3. Add a tag or tagName attribute that can be queried i.e., [tag^="x-"]
@emilio
Copy link
Collaborator

emilio commented Sep 2, 2021

I'm a bit concerned about this defeating many optimizations that engines have for tag selectors. If you have a tag selector you are guaranteed that it'll never impact performance of elements without that tag, but these selectors you'd need to match against all elements.

@astearns
Copy link
Member

astearns commented Sep 2, 2021

@emilio I was thinking something the same, which made me think that the [tag^="x-"] syntax might be best, to give some indication the selector had similar performance characteristics to attribute substring matches.

@castastrophe
Copy link
Author

@astearns I'm partial to that approach myself. It feels clearer and easier for authors to learn/understand. The x-* selector feels strange to me.

@LeaVerou
Copy link
Member

LeaVerou commented Sep 2, 2021

Note that attribute selectors with [tag] wouldn't work, because then there is no way to target an actual tag attribute. I suspect the :is() idea wouldn't work, as we likely don't want to have special parsing rules for within :is() compared to outside :is().

Note that x* might work for element selectors but not attribute names, since [a*=b] already has a defined meaning. Unless we mandate a space after the wildcard? There is precedent for that sort of thing, with space around - and + in calc(). Both a* as well as [a* =b] are currently invalid, so it should be backwards compatible. I think the wildcard approach would be my personal preference. It's simple, it's clear, and it feels very intuitive.

@Westbrook
Copy link

Westbrook commented Sep 2, 2021

+1 🎉

Questions:

  • The use of wildcard has some implications of a "blob"-type syntax. Would this be best restricted to {string}* only, or would we have the ability for *{string} or {string}*{string}, etc.? While there is lots of prior art of custom element scoping that that leverages a prepositional namespace,x-*, there is certainly no requirement for this, and the possibility of supporting postpositional namespacing via *{string} is quite interesting.
  • All the approaches here open the possibility for an h* selector, which is awesome! However, the ability for that to point to h1-6 and html and h-card, etc. might be both undesired or just plain bad practice. Is that an acceptable future? Should the use of a - in the selector form a structural requirement as well?

@castastrophe
Copy link
Author

@Westbrook There's a good point here that you could easily accidentally target tags you didn't mean to simply from a lack of knowing every tag and which are being used on a page.

Regex proposal would cover an /h[1-6]/ syntax: #1010

@castastrophe
Copy link
Author

castastrophe commented Sep 2, 2021

Another possibility:

  1. Add support for wildcard syntax inside the matches pseudo-selector i.e. :matches(x-*)

@Loirooriol
Copy link
Contributor

I wouldn't pollute :is() with an obscure syntax that can't be used outside of it. And x-* seems confusing because * typically means universal selector. So I would add a new pseudo-class, and borrow the inner syntax from attribute selectors:

:tag(= x-foo) /* like `x-foo` but different specificity */
:tag(^= x-)
:tag($= -foo)
:tag(*= -foo-)
:tag(= div s) /* case sensitive: matches <div> but not <DIV> */

@tabatkins
Copy link
Member

Agree that a pseudo-class is probably the best way to go to allow for the complexity we need without making existing stuff messy. I suspect we want to override the specificity so it still counts as a tag selector for specificity purposes, tho.

Same with attribute names, but keep the normal specificity.

@andy-blum
Copy link

I like the new pseudo-selector idea, but I wonder if instead of :tag, :custom might be better?

:custom /* selects all non-native elements */
:custom(= x-foo) /* like `x-foo` but different specificity */
:custom(^= x-)
:custom($= -foo)
:custom(*= -foo-)
:custom(= div s) /* case sensitive: matches <div> but not <DIV> */

The reason for :custom over :tag is to also include customized elements using the is="" syntax.

For example, <p is="word-count"> and <word-count> are the same element class, but different tag names.

@rthrejheytjyrtj545
Copy link

@andy-blum This would be quite cool, especially considering the combination of :custom with :defined or pseudos associated with Shadow DOM. So it is probably better to open a separate issue so that it does not get lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants