Re: [selectors] Proposal: :n-children() selector

On Sun, Feb 1, 2015 at 11:33 AM, Matt Mastracci <matthew@mastracci.com> wrote:
> (unfortunately I missed this reply earlier as my message ended up getting posted multiple times, which caused a bunch of confusion off-list — sorry!).
>
> I wrote the original message before becoming aware of :has in the new spec so I haven’t had a chance to compare the two.
>
> :n-children() isn’t an perfect analogue to :has() or the subject indicator — it is less powerful, and correspondingly less expensive to implement.
>
> With :has(…), you can select down many levels below the parent. In the case of :n-children(), a rule can only examine the direct children of the parent for matches. This is roughly akin to > vs >>>. div:has(> img) has an analogue with :n-children(), while div:has(img) has no corresponding equivalent.
>
> The “of S” portion of the selector is cribbed from the new nth-child(an+b of S) syntax. While it could be omitted, I believe it wouldn’t add further complexity to the fast selector spec as this feature would be landing in nth-child/nth-last-child, replacing the :nth-match() selector from earlier versions of the spec.
>
> :n-siblings() is effectively equivalent to :nth-child():nth-last-child() plus the sibling selector. :n-children() is a novel construction, but simply does the lookup from the direct parent of those siblings which (again, I believe) is approximately equivalent in complexity to :n-siblings(). While it doesn’t offer the full flexibility of :has, I believe it hoists a number of useful use cases into a selector that can be made performant.

Right.  :n-siblings() is doable today; it could be implemented with a
CSS preprocessor.  :n-children() isn't; it requires :has()-like
functionality.  As you say, though, it doesn't require the full
strength of :has(); it's equivalent to a :has() that only allows a
single child combinator, which previous discussion suggests is
sufficiently cheap that it could happen in the fast profile.

That said, I'd actually prefer not to implement this.  Instead, I'd
prefer to get custom selectors working (at least the declarative alias
kind) as suggested in
<http://dev.w3.org/csswg/css-extensions/#custom-selectors>, so people
can do this themselves if they want it.  Doing this well requires
going a little further than what is currently written in the doc, but
all very believable - basically we need a way to handle plumbing
arguments through from the "custom" pseudo to the expansion, and we
need some better combinators to handle "self and/or siblings", etc.

With that, you could do something like:

@custom-selector $rest:--n-siblings($n)
:nth-child(1):nth-last-child($n) /self-and-siblings/ $rest;

So that writing `.foo:--n-siblings(3)` would become
`:nth-child(1):nth-last-child(3) /self-and-siblings/ .foo` after
expansion.

~TJ

Received on Wednesday, 4 February 2015 04:47:05 UTC