user2006754
user2006754

Reputation: 617

CSS counter-increment is not working for nested div and h3 elements

I can not make my CSS counters work. They do work somehow, but on nesting level decrement they are off.

Here is my test page:

<!DOCTYPE HTML>
<html>
<head>
  <title>Chapter Numbering</title>

  <style type="text/css">
    div {
      counter-reset: myitemcounter;
    }
    h3::before {
      counter-increment: myitemcounter;
      content: counters(myitemcounter, ".") " ";
    }
  </style>
</head>

<body>

  <div>
    <h3>This should be ... 1 </h3>
    <h3>This should be ... 2 </h3>
    <div>
      <h3>This should be ... 2.1 </h3>
      <h3>This should be ... 2.2 </h3>
      <h3>This should be ... 2.3 </h3>
      <div>
        <h3>This should be ... 2.3.1 </h3>
        <h3>This should be ... 2.3.2 </h3>
      </div>
      <h3>This should be ... 2.4 </h3>
      <div>
        <h3>This should be ... 2.4.1 </h3>
      </div>
    </div>
    <h3>This should be ... 3 </h3>
    <div>
      <h3>This should be ... 3.1 </h3>
      <h3>This should be ... 3.2 </h3>
    </div>
  </div>

</body>
</html>

The expected numbers are in the text of the heading items. Actual output is (wrong after 2.3.2):

1     This should be ... 1
2     This should be ... 2
2.1   This should be ... 2.1
2.2   This should be ... 2.2
2.3   This should be ... 2.3
2.3.1 This should be ... 2.3.1
2.3.2 This should be ... 2.3.2
2.3.3 This should be ... 2.4
2.3.1 This should be ... 2.4.1
2.4   This should be ... 3
2.1   This should be ... 3.1
2.2   This should be ... 3.2

Thanks for your help.

Upvotes: 5

Views: 2585

Answers (1)

James Montagne
James Montagne

Reputation: 78650

From the spec:

The scope of a counter starts at the first element in the document that has a 'counter-reset' for that counter and includes the element's descendants and its following siblings with their descendants.

The important point is that the scope of the counter created by reset is the siblings and following siblings. As a result, when you reset on div, this also applies to any following h3 elements.

You can get this to work the way you expect by instead resetting the counter on the first child of a div:

div > :first-child {
    counter-reset: myitemcounter;
}

http://jsfiddle.net/9eabn3L3/6

div > :first-child {
    counter-reset: myitemcounter;
}
h3::before {
    counter-increment: myitemcounter;
    content: counters(myitemcounter, ".")" ";
}
<div>
    <h3>This should be ... 1 </h3>
    <h3>This should be ... 2 </h3>
    <div>
        <h3>This should be ... 2.1 </h3>
        <h3>This should be ... 2.2 </h3>
        <h3>This should be ... 2.3 </h3>
        <div>
            <h3>This should be ... 2.3.1 </h3>
            <h3>This should be ... 2.3.2 </h3>
        </div>
        <h3>This should be ... 2.4 </h3>
        <div>
            <h3>This should be ... 2.4.1 </h3>
        </div>
    </div>
    <h3>This should be ... 3 </h3>
    <div>
        <h3>This should be ... 3.1 </h3>
        <h3>This should be ... 3.2 </h3>
    </div>
</div>

Upvotes: 6

Related Questions