Re: [csswg-drafts] [css-selectors-5] Proposal: `:capture()` and `:group()` functional pseudo-classes (#13368)

After having read through the linked thread and having a thought about it, I have come to like the following syntax for the first example there:

```
:capture(input[value^=*]) + ul :group(data-name)
```

There are no changes to the argument of `:capture()` here, just to `:group()`

First, you likely don't need a ton of capture groups in one selector list all that often, so the number made is optional. The absence of a number implies 1.

Second, `each application must be unique` is getting strengthened to `captures are strongly ordered`. This does not matter in a majority of cases with only compound selectors, but is important here for two reasons. The more niche reason is because of complex selectors: `:capture(table.* td.*)` means 'collect classes of tables with td descendants with at least one class, and put that in list one. collect classes of tds which have table ancestors with at least one class, and put that in list two. the `group()` will match all elements with a class in list two which have an ancestor with a class from list one.'

The more important reason is to allow the second modification to the argument for `:group()`: value-attribution. The new argument to `:group()` is a list (`#?`) of value-attribution statements. A value-attribution statement consists of an optional signless-integer, and 0 or more identifiers, separated by whitespace. Some examples:
```
:group(1 data-name, 4)
:group()
:group(value, data-name, 3 value data-name)
```
These identifiers assign which attribute to match against for captured `value` values (of the form `:capture([foo=*])`). If a `value` is captured but unassigned, it will try to match against any attribute. If there are more assignments than values captured, any extra assignments are ignored. If the signless-integer is greater than the number of `:capture()`s in scope, its value-attribution statement is ignored.

Finally, scope. Any `:capture()`s which are part of a selector-list which is a direct ancestor is in scope. For example:
```css
:capture(div.*) :capture(table#*), /* :group()s anywhere in this selector list have 3 :capture()s in scope */
h1 > :capture(p[*]) {
  table:capture(*:hover + *) /* :group()s in this sl have 4 :capture()s in scope */ {
    tr td /* 4 :capture()s in scope */ {
    }
    :capture(table.wide[foo*=*] tr.*), /* 6 :capture()s in scope */
    table :capture(tr.thin[*]),
    :group(5 fooer) tr {
    }
    table td :capture(span#*) /* 5 :capture()s in scope */ {
    }
  }
  table:not(:hover) /* 3 :capture()s in scope */ {
  }
  :group(2) tr:capture(.*:capture([*])) /* 5 :capture()s in scope */ {
  }
}
```

-- 
GitHub Notification of comment by rokke-git
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13368#issuecomment-3777476925 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 21 January 2026 11:01:04 UTC