- From: D7460N via GitHub <noreply@w3.org>
- Date: Thu, 07 May 2026 07:07:27 +0000
- To: public-css-archive@w3.org
## Smell test
Just had this conversation . . .
Dev: "CSS is broken."
Me: "Yeah, funny meme."
Dev: "No, seriously. LIs don't even work. Numbers show, but that's it. Can't do [expletive] with them. Same with counters. Half baked."
Me: "It's purposeful".
Dev: ". . . F'ing hate CSS."
## Fail
The browser already computes counter values for every list item. To render `::marker`. To fill `counter()` in `content:`. To honor `<ol start>`, `<ol reversed>`, `<li value>`, `@counter-style`, scoped `counter-reset`. The user sees the values on screen.
**_CSS can't read them._**
That's the whole problem. The engine knows. The language refuses to surface what the engine knows.
```css
li { --i: counter-value(list-item); }
```
Returns `<integer>`. Usable in `calc()`, custom properties, `@container style()`. Same shape as `sibling-index()`, but counter-aware.
[@tabatkins endorsed this exact shape](https://github.com/w3c/csswg-drafts/issues/1026): typed retrieval, parallel to the `attr()` `type()` extension. [@LeaVerou said it directly](https://github.com/w3c/csswg-drafts/issues/1026): *"I would much rather see something that works like `counter()` but produces a number."*
> "We have `sibling-index()`"
`sibling-index()` ignores `<ol start>`, `<ol reversed>`, `<li value>`, custom `@counter-style`, nested counter scopes, and author-defined increments. It answers a different question.
Authors who use semantic HTML correctly, declaring `start`, `value`, `reversed`, get their semantics honored visually, but _**not programmatically**_. The browser respects what they declared, but _**CSS doesn't**_.
If `sibling-index()` were the answer, the [Chromium `@property` hack](https://github.com/w3c/csswg-drafts/issues/1026) wouldn't exist. Authors chose the hack anyway, because it does what `sibling-index()` can't.
> This would break parallel style computation. [@upsuper, 2017](https://github.com/w3c/csswg-drafts/issues/1026):
1. **`sibling-index()` shipped.** Same structural shape, tree-derived integer at style time. Engines parallelized what they could and serialized the rest.
2. **`:has()` shipped.** Twenty years of *"this breaks invalidation"* turned out to be bounded. Engines built new strategies.
3. **The Chromium `@property` hack works.** Register a custom property as `<number>`; counter values flow through. If parallelization were broken, neither would the hack.
Already answered. [@kizu's `counter-value-scope`](https://github.com/w3c/csswg-drafts/issues/1026) covers any remaining concern: opt-in to the slower path per counter. Authors who don't use it pay nothing.
Paged-media counters (`page`, `pages`, `target-counter()`). [@faceless2's analysis](https://github.com/w3c/csswg-drafts/issues/1026) have real layout-feedback loops. Defer them. Different problem.
Document-flow counters don't have that shape. Tree + counter rules, resolved before layout. Same dependency direction as `sibling-index()`.
> "Few authors need this"
This dismissal has been the response for nine years. Yet:
- Demand (frustration) keeps accumulating.
- Workarounds have multiplied: `:nth-child()` chains, JavaScript walkers, `data-*` mirrors, the `@property` hack.
- Implementations have demonstrated the capability.
- And CSS advocates like myself have little to justify it.
An author community writing blog posts for an undocumented hack is not a niche. The question is not whether authors need this. The question is how much longer the standard will require us to prove it.
--
GitHub Notification of comment by dragontheory
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/1026#issuecomment-4394902075 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Thursday, 7 May 2026 07:07:28 UTC