w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.51k stars 671 forks source link

[selectors] `/idref()/` combinator to follow element references for arbitrary IDREF attributes #10970

Open LeaVerou opened 1 month ago

LeaVerou commented 1 month ago

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:

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 commented 1 month ago

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

bradkemper commented 1 month ago

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 commented 1 month ago

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?:

https://github.com/w3c/csswg-drafts/issues/397

bradkemper commented 1 month ago

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 commented 1 month ago

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

LeaVerou commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

@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 commented 1 month ago

@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 commented 1 month ago

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