v154 · css · counter styles
CSS symbols()
Marking a list with your own symbols meant declaring a named @counter-style at the top level and referring to it by name — a global name, for something used in one place. symbols() builds an anonymous counter style inline, wherever a counter style is accepted.
concepts
-
The five systems
cyclic,numeric,alphabetic,symbolicandfixedapplied to the same symbols and the same list, so the difference between them is a comparison instead of a paragraph. The interesting one is what each does when the list outruns the symbols. -
Inline against @counter-style
The same result written both ways, with the boilerplate counted, plus the case that motivates the change: two components that each want a private counter style and would otherwise be fighting over one global namespace.
-
In counter() and content
symbols()is accepted bycounter()andcounters()too, so a nested outline can be numbered with your own symbols per level — built here as a live document tree.
why it shipped
@counter-style is a top-level at-rule with a global name, which makes it awkward for exactly the case it is most used for: one component, one list, one set of markers. The name has to be invented, kept unique across the whole stylesheet, and shipped whether or not anything still uses it — the same problems that made anonymous functions preferable to named ones for one-off callbacks.
symbols() is the inline form. It takes a list of strings and an optional system, and it can appear anywhere a counter style is accepted: list-style-type, the list-style shorthand, and inside counter() and counters().
the API
/* Cycles through the symbols; the default system. */
.steps { list-style-type: symbols("◆" "◇"); }
/* Counts in a positional system, so it keeps working past the list. */
.figures { list-style-type: symbols(numeric "0" "1"); }
/* Anywhere a counter style is accepted. */
.outline li::before {
content: counters(item, ".", symbols(alphabetic "a" "b" "c")) " ";
}