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] /idref()/ combinator to follow element references for arbitrary IDREF attributes #10970

Open
LeaVerou opened this issue Sep 27, 2024 · 10 comments

Comments

@LeaVerou
Copy link
Member

In the past we have been discussing a /for/ combinator to go from a label to the input it references (cannot find the issue now). However, HTML is rife with several IDREF attributes. Here is a small subset:

  • for, in <label> and <output>
  • list in <input>
  • A host of ARIA attributes (e.g. aria-describedby, aria-labelledby, aria-activedescendant, aria-controls, aria-details, aria-flowto, aria-owns etc.)
  • Popovers (popovertarget)
  • Invokers (invoketarget)
  • anchor
  • Plus, web component authors can always define their own, custom IDREF attributes

It seems clear that the path forwards for future combinators is '/' <ident> '/'. But that also opens the path for having functional combinators. What if we define a combinator that takes any attribute as a parameter and treats it as an IDREF?
Then /for/ becomes:

label /idref(for)/ input {
	/* ... */
}

but also things like this are possible:

input.country /idref(list)/ datalist {
	/* ... */
}

Or even:

my-tooltip /idref(for)/ * {
	cursor: help;
}
@flashymittens
Copy link

Wouldn’t something like label::ref(for) be more compatible and simple?

@bradkemper
Copy link
Contributor

bradkemper commented Sep 28, 2024

A pseudo element would be less useful, because you wouldn’t be able to select descendants. This, something like this is currently illegal:

label::ref(for) span {}

Edit: not that you would have a span inside an input, so maybe that’s a bad example, but you might want to select an option inside a data list, for example.

@bradkemper
Copy link
Contributor

In the past we have been discussing a /for/ combinator to go from a label to the input it references (cannot find the issue now).

Maybe this one?:

#397

@bradkemper
Copy link
Contributor

I like this idea as far as it goes. The issue I posted above is about going the other direction, i.e. selecting the label from the input. But that’s a separate (important) problem. @LeaVerou’s idea here does sound very useful to me.

@flashymittens
Copy link

@bradkemper ah, I haven’t thought it’s invalid and not merely “not matching anything” 🤔

@LeaVerou
Copy link
Member Author

Wouldn’t something like label::ref(for) be more compatible and simple?

The fact that we have contorted pseudo-elements to facilitate encapsulation in some shadow DOM use cases doesn't mean they are an appropriate replacement for combinators. We should avoid pseudo-elements for targeting entire elements in the light DOM. That’s precisely what combinators are for.

(and IMO we should even ditch pseudo-elements for the shadow DOM use cases, see #7922 and #10939)

@therealglazou
Copy link
Contributor

Hellooooo Lea :-)

Selection of ID/IDREF agnosticly from the attributes names is an old dream of mine. Long ago, SGML had "paired elements", linked through that mechanism and their styling required such a selecting hint. For those who were around back in the nineties, that was a topic I discussed during the famous Clamart CSS WG meeting.

I think the proposed combinator is not enough, let me explain... The whole thing is, at its roots, about catching a given value from a named attribute on an arbitrary element and finding another arbitrary element catching another named attribute of same value. The common denominator here is the value, the attribute names are only carriers.
The proposed combinator, as a functional thing, specifies only one of these two attributes where it should propose two, the target attribute and the source one, the latter defaulting to "id".

So two choices:

  1. elaborate a mechanism allowing to "store" and "reuse" an attribute value (would be super powerful but CSS isn't a programming language, right ? :-)
  2. make your functional idref combinator dual-valued with an "id" default if the second parameter is missing

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 2, 2024

@therealglazou I do think there is value in having an even more general combinator that lets you customize the attribute too, but for the sake of simplicity, I thought this is a good first step. Also, I couldn't find a good name/syntax for it that wouldn't complicate the common IDREF case. If you can, that would be great!

@therealglazou
Copy link
Contributor

@LeaVerou I gave second thoughts to this PR. The problem with this combinator is that it has impact on attribute existence above and below the combinator itself. And if the combinator is "generic" enough to allow arbitrary source attributes, the selection algorithm does not know what target attribute has to be present before the combinator is hit in the reverse processing of the chain of selectors. I am therefore not sure any more that a combinator is the optimal solution here. I'm not saying we have much better options, I'm only saying it's going to impact the selection algo in a way that I don't really like... Not sure I'm fully understandable, let me know if it's not clear enough.

@LeaVerou
Copy link
Member Author

Yeah, I'm afraid I don't understand what you mean at all 😕

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

No branches or pull requests

4 participants