Numbering and bullets, your way
CSS list markers are not limited to 1. and •. A large set of predefined counter
styles cover numeric, alphabetic, Roman, Greek, CJK and symbolic numbering, and the
@counter-style at-rule lets you invent your own. This reference lists the common
built-ins, the rule’s descriptors, and renders a number into several styles live.
How it works
A counter style maps an integer to a marker string. The built-ins fall into families:
numeric (positional, like decimal), alphabetic (bijective base-N letters),
additive (weighted symbols summed together, like Roman numerals and Hebrew), and
symbolic (a fixed glyph such as disc). The live demo above implements the real
algorithms: bijective base-26 for lower-alpha, subtractive Roman assembly for
upper-roman, and zero-padding for decimal-leading-zero.
To define a custom style, write @counter-style name { system: …; symbols: …; }. The
system chooses the algorithm, symbols or additive-symbols supply the glyphs, and
range, pad, negative, prefix, suffix and fallback refine the output.
Outside the declared range, or for unrepresentable values, the fallback style
(default decimal) takes over.
Custom counter styles in practice
Zero-padded step numbers — for a tutorial with steps 01, 02 … 09, 10:
@counter-style padded-decimal {
system: extends decimal;
pad: 2 "0";
}
ol { list-style-type: padded-decimal; }
The extends decimal system reuses the standard numeric algorithm but applies
pad: 2 "0" to ensure at least two characters, so 1 becomes 01.
Emoji bullets — purely decorative markers using cyclic repetition:
@counter-style stars {
system: cyclic;
symbols: "★" "☆";
suffix: " ";
}
ul.fancy { list-style-type: stars; }
cyclic repeats through the symbols list, so items alternate between filled and
outlined stars. The suffix replaces the default ". " for numeric styles.
Roman numeral appendix with a decimal fallback:
@counter-style appendix {
system: additive;
additive-symbols: 1000 "M", 900 "CM", 500 "D", 400 "CD",
100 "C", 90 "XC", 50 "L", 40 "XL",
10 "X", 9 "IX", 5 "V", 4 "IV",
1 "I";
range: 1 3999;
fallback: decimal;
}
ol.appendix { list-style-type: appendix; }
The range: 1 3999 matches the practical range for Roman numerals; items outside
it fall back to plain decimal.
Tips and examples
- Apply a style with
list-style-type, or reuse it anywhere via thecounter()andcounters()functions incontent. - Always set a sensible
rangeandfallbackfor additive styles so zero and large numbers stay legible. system: extends decimalis the easy way to tweak only the prefix or suffix of an existing style without re-listing every symbol.- Predefined symbolic markers (
disc,circle,square) ignore the counter value — they repeat the same glyph for every item. - The
negativedescriptor controls what is prepended and appended for negative counter values; its default is a minus sign prepended, but you can change both parts.