[csswg-drafts] [css-selectors] [css-values] Proposal: "Middle Out" sibling selectors (#8483)

caucik has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-selectors] [css-values] Proposal: "Middle Out" sibling selectors ==
Currently we can select elements using [:nth-child](https://drafts.csswg.org/selectors/#the-nth-child-pseudo), [:nth-last-child](https://drafts.csswg.org/selectors/#the-nth-last-child-pseudo), [:nth-of-type](https://drafts.csswg.org/selectors/#the-nth-of-type-pseudo) and [:nth-last-of-type](https://drafts.csswg.org/selectors/#the-nth-last-of-type-pseudo) based on [An+B [of S]](https://drafts.csswg.org/css-syntax-3/#anb-microsyntax) from either **beginning** or **end** of the list of siblings.

These selectors also work great with dynamic number of siblings. We can specify for example every 3rd element starting from 5th, first/last 3 elements etc. regardless of the number of siblings in the collection.

Oftentimes we need to select sibling nodes **around** given element (pagination, breadcrumb navigation, effects around :hover-ed element like [this](https://codepen.io/pouriversal/pen/yLvdwQW) or [this](https://codepen.io/chriscoyier/pen/qBoogaX) etc.).

We can utilize [E + F](https://drafts.csswg.org/selectors/#adjacent-sibling-combinators) and [:has()](https://drafts.csswg.org/selectors/#relational) selectors but there are multiple problems with it. Apart from the apparent asymmetry of the "forward" vs. "backward" selectors in the rule it only works for **fixed** number of sibling elements. And so for fixed solution we need to specify **one rule** per **one level** of siblings **around** given element:

- first level around (select one sibling before and one after):
```
li:has(+ li:hover),
li:hover + li { ... }
```

- second level around:
```
li:has(+ li + li:hover),
li:hover + li + li { ... }
```

- third level around:
```
li:has(+ li + li + li:hover),
li:hover + li + li + li { ... }
```

It is a solution but not a pretty one nor a dynamic one. It is also not immediately obvious what it means. Therefore it's closer to a hack than to clean solution.

I propose two new pseudo selectors with obvious functionality:

### :nth-prev-sibling(An+B [of S]?)
and
### :nth-next-sibling(An+B [of S]?)

With these two selectors we can conveniently select elements the same way as using current pseudo selectors mentioned in first paragraph of this proposal **but** instead of **anchoring** at the beginning or end of nodeList we can **anchor at the selected element** anywhere inside of nodeList.

A few examples:

a a a a a a a **a.active** a a a a a a a a

to select 1 element before a.active:
`a.active:nth-prev-sibling(1)`

to select all but first 3 elements after a.active
`a.active:not(:nth-next-sibling(-n+3))`

Obviously [it won't be free](https://snook.ca/archives/html_and_css/css-parent-selectors). But we already have [:not()](https://drafts.csswg.org/selectors/#negation) and [:has()](https://drafts.csswg.org/selectors/#relational) so why bother.


Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/8483 using your GitHub account


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

Received on Tuesday, 21 February 2023 22:01:46 UTC