CSS / List counter-reset and the start attribute
In CSS, we can create a custom list numbering with counter-reset
, counter-increment
and counter()
functions.
For example:
ol {
counter-reset: olcounter;
li {
counter-increment: olcounter;
&::before {
content: counter(olcounter) ". ";
}
}
}
This approach works fine for most of the continuous list, for example:
<ol>
<li>first item</li>
<li>second item</li>
<li>third item</li>
</ol>
But sometimes, you will have a list with a much more complex structure, the HTML structure would not be continuous. For example, when using a markdown generator on the following content:
This is a list:
1. First item
Another line here
2. Second item
Some more lines
Ok?
3. Third item
The generated HTML structure would be broken up into multiple <ol>
tags. They are technically multiple lists, but each of them has the start
attribute to specify the start value of the list. So they would look like a continuous list.
<ol start="1">
<li>
<p>First item</p>
<p>Another line here</p>
</li>
</ol>
<ol start="2">
<li>
<p>Second item</p>
<p>Some more lines</p>
<p>Ok?</p>
</li>
</ol>
<ol start="3">
<li>
<p>Third item</p>
</li>
</ol>
If we are using the CSS style defined from the beginning of the post, the rendered list would look wrong, all the list items will start with 1 instead of incrementing:
1. First item
Another line here
1. Second item
Some more lines
Ok?
1. Third item
The reason for this behavior is, we are resetting the counter at the beginning of each <ol>
element.
ol {
counter-reset: olcounter;
}
To fix the problem, we should ignore the counter reset if the start
attribute is presented, it can be done with the following CSS selector:
ol {
counter-reset: olcounter;
&[start] {
counter-reset: none;
}
}
Please note that this approach does not really respect the value of the start
attribute. If you want to make counter-reset
respect the value of the start
attribute, a possible approach is to use JavaScript to inline the style for each <ol>
element, like this:
const olWithStarts = document.querySelectorAll("ol[start]");
olWithStarts.forEach(ol => {
const start = ol.getAttribute('start');
ol.style = 'counter-reset: olcounter ' + start;
});