document use rules apply.
This module introduces the @counter-style rule, which allows authors to define their own custom counter styles for use with CSS list-marker and generated-content counters [CSS3LIST]. It also predefines a set of common counter styles, including the ones present in CSS2 and CSS2.1.
CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, in speech, etc.This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
Publication as a Last Call Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
The (archived) public mailing list [email protected] (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “css-counter-styles” in the subject, preferably like this: “[css-counter-styles] …summary of comment…”
This document was produced by the CSS Working Group (part of the Style Activity).
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This specification is a Last Call Working Draft. All persons are encouraged to review this document and send comments to the www-style mailing list as described above. The deadline for comments is 23 September 2014.
The following features are at-risk, and may be dropped during the CR period:
CSS 1 defined a handful of useful counter styles based on the styles that HTML traditionally allowed on ordered and unordered lists. While this was expanded slightly by CSS2.1, it doesn’t address the needs of worldwide typography.
This module introduces the @counter-style rule which allows CSS to address this in an open-ended manner, by allowing the author to define their own counter styles. These styles can then be used in the list-style-type property or in the counters() functions. It also defines some additional predefined counter styles, particularly ones which are common but complicated to represent with @counter-style.
A counter style defines how to convert a counter value into a string. Counter styles are composed of:
When asked to generate a counter representation using a particular counter style for a particular counter value, follow these steps:
Note: the prefix and suffix don’t play a part in this algorithm. This is intentional; the prefix and suffix aren’t part of the string returned by the counter() or counters() functions. Instead, the prefix and suffix are added by the algorithm that constructs the value of the content property for the ::marker pseudo-element. This also implies that the prefix and suffix always come from the specified counter-style, even if the actual representation is constructed by a fallback style.
Some values of system (symbolic, additive) and some descriptors (pad) can generate representations with size linear to an author-supplied number. This can potentially be abused to generate excessively large representations and consume undue amounts of the user’s memory or even hang their browser. User agents must support representations at least 60 Unicode codepoints long, but they may choose to instead use the fallback style for representations that would be longer than 60 codepoints.
The @counter-style rule allows authors to define a custom counter style. The components of a counter style are specified by descriptors in the @counter-style rule. The algorithm is specified implicitly by a combination of the system, symbols, and additive-symbols properties.
The general form of an @counter-style rule is:
@counter-style <counter-style-name> { <declaration-list> }
where <counter-style-name> is a <custom-ident>.
If a counter style’s name is an ASCII case-insensitive match for "decimal" or "none", the @counter-style rule is invalid.
Note: Note that CSS-wide keywords. In addition, some names, like inside, are valid as counter style names, but conflict with the existing values of properties like list-style, and so won’t be usable there.
Counter style names are case-sensitive. However, the names defined in this specification are ASCII lower-cased on parse wherever they are used as counter styles, e.g. in the list-style set of properties, in the @counter-style rule, and in the counter() functions.
Each @counter-style rule specifies a value for every counter-style descriptor, either implicitly or explicitly. Those not given explicit value in the rule take the initial value listed with each descriptor in this specification. These descriptors apply solely within the context of the @counter-style rule in which they are defined, and do not apply to document language elements. There is no notion of which elements the descriptors apply to or whether the values are inherited by child elements. When a given descriptor occurs multiple times in a given @counter-style rule, only the last specified value is used; all prior values for that descriptor must be ignored.
Defining a @counter-style makes it available to the entire document in which it is included. If multiple @counter-style rules are defined with the same name, only one wins, according to standard cascade rules. @counter-style rules cascade "atomically": if one replaces another of the same name, it replaces it entirely, rather than just replacing the specific descriptors it specifies.
Note: Note that even the predefined counter styles can be overridden; the UA stylesheet occurs before any other stylesheets, so the predefined ones always lose in the cascade.
This at-rule conforms with the forward-compatible parsing requirement of CSS; conformant parsers that don’t understand these rules will ignore them without error. Any descriptors that are not recognized or implemented by a given user agent, or whose value does not match the grammars given here or in a future version of this specification, must be ignored in their entirety; they do not make the @counter-style rule invalid.
| Name: | system |
|---|---|
| For: | @counter-style |
| Value: | cyclic | additive | [ extends <counter-style-name> ] |
| Initial: | symbolic |
The system descriptor specifies which algorithm will be used to construct the counter’s representation based on the counter value. For example, cyclic counter styles just cycle through their symbols repeatedly, while numeric counter styles interpret their symbols as digits and build their representation accordingly. The systems are defined as follows:
The cyclic counter system cycles repeatedly through its provided symbols, looping back to the beginning when it reaches the end of the list. It can be used for simple bullets (just provide a single counter symbol), or for cycling through multiple symbols. The first counter symbol is used as the representation of the value 1, the second counter symbol (if it exists) is used as the representation of the value 2, etc.
If the system is cyclic, the symbols descriptor must contain at least one counter symbol, or else the @counter-style rule is invalid. This system is defined over all counter values.
@counter-style triangle { system: cyclic; symbols: ‣; suffix: " "; }
It will then produce lists that look like:
‣ One ‣ Two ‣ Three
If there are N counter symbols and a representation is being constructed for the integer value, the representation is the counter symbol at index ( (value-1) mod N) of the list of counter symbols (0-indexed).
The fixed counter system runs through its list of counter symbols once, then falls back. It is useful for representing counter styles that only have a finite number of representations. For example, Unicode defines several limited-length runs of special characters meant for lists, such as circled digits.
If the system is fixed, the symbols descriptor must contain at least one counter symbol, or else the @counter-style rule is invalid. This system is defined over counter values in a finite range, starting with the first symbol value and having a length equal to the length of the list of counter symbols.
When this system is specified, it may optionally have an integer provided after it, which sets the first symbol value. If it is omitted, the first symbol value is 1.
@counter-style box-corner { system: fixed; symbols: ◰ ◳ ◲ ◱; suffix: ': '; }
It will then produce lists that look like:
◰: One ◳: Two ◲: Three ◱: Four 5: Five 6: Six
The first counter symbol is the representation for the first symbol value, and subsequent counter values are represented by subsequent counter symbols. Once the list of counter symbols is exhausted, further values cannot be represented by this counter style, and must instead be represented by the fallback counter style.
The symbolic counter system cycles repeatedly through its provided symbols, doubling, tripling, etc. the symbols on each successive pass through the list. For example, if the original symbols were "*" and "†", then on the second pass they would instead be "**" and "††", while on the third they would be "***"and "†††", etc. It can be used for footnote-style markers, and is also sometimes used for alphabetic-style lists for a slightly different presentation than what the alphabetic system presents.
If the system is symbolic, the symbols descriptor must contain at least one counter symbol, or else the @counter-style rule is invalid. This system is defined only over strictly positive counter values.
@counter-style footnote { system: symbolic; symbols: '*' ⁑ † ‡; suffix: " "; }
It will then produce lists that look like:
* One ⁑ Two † Three ‡ Four ** Five ⁑⁑ Six
@counter-style upper-alpha-legal { system: symbolic; symbols: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z; }
This style is identical to upper-alpha through the first 27 values, but they diverge after that, with upper-alpha going "AB", "AC", "AD", etc. Starting at the 53rd value, upper-alpha goes "BA", "BB", "BC", etc., while this style jumps into triple digits with "AAA", "BBB", "CCC", etc.
To construct the representation, run the following algorithm:
Let N be the length of the list of counter symbols, value initially be the counter value, S initially be the empty string, and symbol(n) be the nth counter symbol in the list of counter symbols (0-indexed).
symbol( (value - 1) mod N).
ceil( value / N ).
Finally, return S.
The alphabetic counter system interprets the list of counter symbols as digits to an alphabetic numbering system, similar to the default lower-alpha counter style, which wraps from "a", "b", "c", to "aa", "ab", "ac". Alphabetic numbering systems do not contain a digit representing 0; so the first value when a new digit is added is composed solely of the first digit. Alphabetic numbering systems are commonly used for lists, and also appear in many spreadsheet programs to number columns. The first counter symbol in the list is interpreted as the digit 1, the second as the digit 2, and so on.
If the system is alphabetic, the symbols descriptor must contain at least two counter symbols, or else the @counter-style rule is invalid. This system is defined only over strictly positive counter values.
@counter-style go { system: alphabetic; symbols: url(white.svg) url(black.svg); suffix: " "; }
It will then produce lists that look like:
Note: This example requires support for SVG images to display correctly.
If there are N counter symbols, the representation is a base N alphabetic number using the counter symbols as digits. To construct the representation, run the following algorithm:
Let N be the length of the list of counter symbols, value initially be the counter value, S initially be the empty string, and symbol(n) be the nth counter symbol in the list of counter symbols (0-indexed).
While value is not equal to 0:
value - 1.
floor( value / N ).
Finally, return S.
The numeric counter system interprets the list of counter symbols as digits to a "place-value" numbering system, similar to the default decimal counter style. The first counter symbol in the list is interpreted as the digit 0, the second as the digit 1, and so on.
If the system is numeric, the symbols descriptor must contain at least two counter symbols, or else the @counter-style rule is invalid. This system is defined over all counter values.
@counter-style trinary { system: numeric; symbols: '0' '1' '2'; }
It will then produce lists that look like:
1. One 2. Two 10. Three 11. Four 12. Five 20. Six
If there are N counter symbols, the representation is a base N number using the counter symbols as digits. To construct the representation, run the following algorithm:
Let N be the length of the list of counter symbols, value initially be the counter value, S initially be the empty string, and symbol(n) be the nth counter symbol in the list of counter symbols (0-indexed).
floor( value / N ).
The additive counter system is used to represent "sign-value" numbering systems, which, rather than using reusing digits in different positions to change their value, define additional digits with much larger values, so that the value of the number can be obtained by adding all the digits together. This is used in Roman numerals and other numbering systems around the world.
If the system is additive, the additive-symbols descriptor must contain at least one additive tuple, or else the @counter-style rule is invalid. This system is nominally defined over all counter values (see algorithm, below, for exact details).
@counter-style dice { system: additive; additive-symbols: 6 ⚅, 5 ⚄, 4 ⚃, 3 ⚂, 2 ⚁, 1 ⚀; suffix: " "; }
It will then produce lists that look like:
⚀ One ⚁ Two ⚂ Three ... ⚅⚄ Eleven ⚅⚅ Twelve ⚅⚅⚀ Thirteen
To construct the representation, run this algorithm:
Let value initially be the counter value, S initially be the empty string, and symbol list initially be the list of additive tuples.
floor( value / current tuple’s weight )
times (this may be 0).
Note: All of the predefined additive @counter-style rules in this specification produce representations for every value in their range, but it’s possible to produce values for additive-symbols that will fail to find a representation with the algorithm defined above, even though theoretically a representation could be found. For example, if a @counter-style was defined with additive-symbols: 3 "a", 2 "b";, the algorithm defined above will fail to find a representation for a counter value of 4, even though theoretically a "bb" representation would work. While unfortunate, this is required to maintain the property that the algorithm runs in linear time relative to the size of the counter value.
The extends system allows an author to use the algorithm of another counter style, but alter other aspects, such as the negative sign or the suffix. If a counter style uses the extends system, any unspecified descriptors must be taken from the extended counter style specified, rather than taking their initial values.
If a @counter-style uses the extends system, it must not contain a symbols or additive-symbols descriptor, or else the @counter-style rule is invalid.
If the specified counter style name isn’t the name of any currently-defined counter style, it must be treated as if it was extending the decimal counter style. If one or more @counter-style rules form a cycle with their extends values, all of the counter styles participating in the cycle must be treated as if they were extending the decimal counter style instead.
1) first item 2) second item 3) third item
Rather than writing up an entirely new counter style, this can be done by just extending decimal:
@counter-style decimal-paren {
system: extends decimal;
suffix: ") ";
}
| Name: | negative |
|---|---|
| For: | @counter-style |
| Value: | <symbol> <symbol>? |
| Initial: | "\2D" ("-" hyphen-minus) |
The negative descriptor defines how to alter the representation when the counter value is negative.
The first <symbol> in the value is prepended to the representation when the counter value is negative. The second <symbol>, if specified, is appended to the representation when the counter value is negative.
Not all system values use a negative sign. In particular, a counter style uses a negative sign if its system value is symbolic, alphabetic, numeric, additive, or extends if the extended counter style itself uses a negative sign. If a counter style does not use a negative sign, it ignores the negative sign when generating a counter representation.
| Name: | prefix |
|---|---|
| For: | @counter-style |
| Value: | <symbol> |
| Initial: | "" (the empty string) |
The prefix descriptor specifies a <symbol> that is prepended to the marker representation. Prefixes are only added by the algorithm for constructing the default contents of the ::marker pseudo-element; the prefix is not added automatically when the counter() or counters() functions are used. Prefixes come before any negative sign.
| Name: | suffix |
|---|---|
| For: | @counter-style |
| Value: | <symbol> |
| Initial: | "\2E\20" ("." full stop followed by a space) |
The suffix descriptor specifies a <symbol> that is appended to the marker representation. Suffixes are only added by the algorithm for constructing the default contents of the ::marker pseudo-element; the suffix is not added automatically when the counter() or counters() functions are used. Suffixes are added to the representation after negative signs.
| Name: | range | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| For: | @counter-style | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Value: | [ [ auto
If the lower bound of any range is higher than the upper bound, the entire descriptor is invalid and must be ignored. Implementations must support ranges with a lower bound of at least -215 and an upper bound of at least 215-1 (the range of a signed 2-byte int). They may support higher ranges. If any specified bound is outside of the implementation’s supported bounds, it must be treated as the closest bound that the implementation does support. 3.6 Zero-Padding and Constant-Width Representations: the pad descriptor
The pad descriptor allows an author to specify a "fixed-width" counter style, where representations shorter than the pad value are padded with a particular <symbol>. Representations larger than the specified pad value are constructed as normal.
The most common example of "fixed-width" numbering is zero-padded decimal numbering.
If an author knows that the numbers used will be less than a thousand, for example,
it can be zero-padded with a simple pad: 3 "0"; descriptor,
ensuring that all of the representations are 3 digits wide.
This will cause, for example, 1 to be represented as "001", 20 to be represented as "020", 300 to be represented as "300", 4000 to be represented as "4000", and -5 to be represented as "-05". Note: The pad descriptor counts the number of grapheme clusters in the representation, but pads it with <symbol>s. If the specified pad <symbol> is multi-character, this will likely not have the desired effect. Unfortunately, there’s no way to use the number of grapheme clusters in the pad <symbol> without violating useful constraints. It is recommended that authors only specify <symbol>s of a single grapheme cluster in the pad descriptor. 3.7 Defining fallback: the fallback descriptor
The fallback descriptor specifies a fallback counter style to be used when the current counter style can’t create a representation for a given counter value. For example, if a counter style defined with a range of 1-10 is asked to represent a counter value of 11, the counter value’s representation is instead constructed with the fallback counter style (or possibly the fallback style’s fallback style, if the fallback style can’t represent that value, etc.). If the value of the fallback descriptor isn’t the name of any currently-defined counter style, the used value of the fallback descriptor is decimal instead. Similarly, while following fallbacks to find a counter style that can render the given counter value, if a loop in the specified fallbacks is detected, the decimal style must be used instead. Note that it is not necessarily an error to specify fallback loops. For example, if an author desires a counter style with significantly different representations for even and odd counter values, they may find it easiest to define one style that can only represent odd values and one that can only represent even values, and specify each as the fallback for the other one. Though the fallback graph is circular, at no point do you encounter a loop while following these fallbacks - every counter value is represented by one or the other counter style. 3.8 Marker characters: the symbols and additive-symbols descriptors
Issues Index
Is there a better suffix to use than the initial (".")?
The alphabetic ethiopic systems use a different suffix.
↵
Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||