Search code examples
csscss-counter

CSS counter-reset on nested list


I'm struggling with counter-reset when ol is in div. Red list in the snippet numbering should be:

1, 2, 3

not:

3.1, 3.2, 3.3,

ol {
    counter-reset: item;
    list-style: none;
}
li:before {
    counter-increment: item;
    content: counters(item, ".")" ";
}
<ol>
    <li>BBD</li>
    <li>BBD
        <ol>
            <li>BBD</li>
            <li>BBD</li>
            <li>BBD</li>
        </ol>
    </li>
    <li>BBD</li>
</ol>

<ol>
    <li>BBD</li>
    <li>BBD</li>
    <li>BBD</li>
</ol>

<div>
    <ol style="color:red;">
        <li>BBD</li>
        <li>BBD</li>
        <li>BBD</li>
    </ol>
</div>

http://jsfiddle.net/1dab8xs7/1/


Solution

  • Your issue isn't with the counter-reset property, it is with the content property and the counters() function. This function atomaticaly adds a new instance for each nested element. This is great for the nested ol elements but it also adds a counter instance when the first level ol is nested in any other element.

    So you should use the counter() function on the first level ol elements and keep the counters() (notice the "s") function on the second level one :

    More info on MDN about nesting counters

    ol {
        counter-reset: item;
        list-style: none;
    }
    li:before {
        counter-increment: item;
        content: counter(item)". ";
    }
    ol ol li:before{
      content: counters(item,".") " ";
    }
    <ol>
        <li>BBD</li>
        <li>BBD
            <ol>
                <li>BBD</li>
                <li>BBD</li>
                <li>BBD</li>
            </ol>
        </li>
        <li>BBD</li>
    </ol>
    
    <ol>
        <li>BBD</li>
        <li>BBD</li>
        <li>BBD</li>
    </ol>
    
    <div>
        <ol style="color:red;">
            <li>BBD</li>
            <li>BBD</li>
            <li>BBD</li>
        </ol>
    </div>


    As suggested by @harry, you can also set the counter reset on the first child of the ol element, either with the li:first-child pseudo class or with the ol::before pseudo element, example :

    ol{
        list-style: none;
    }
    li:first-child{
        counter-reset: item;
    }
    /* or
    ol:before {
        content: '';
        counter-reset: item;
    }
    */
    li:before {
        counter-increment: item;
        content: counters(item, ".")" ";
    }
    <ol>
        <li>BBD</li>
        <li>BBD
            <ol>
                <li>BBD</li>
                <li>BBD</li>
                <li>BBD</li>
            </ol>
        </li>
        <li>BBD</li>
    </ol>
    
    <ol>
        <li>BBD</li>
        <li>BBD</li>
        <li>BBD</li>
    </ol>
    
    <div>
        <ol style="color:red;">
            <li>BBD</li>
            <li>BBD</li>
            <li>BBD</li>
        </ol>
    </div>