fuuchi
fuuchi

Reputation: 59

CSS counter - numbered headings in different div

I'm trying to make numbered headings with CSS counters and it works pretty good when all headings are in same div, but when I need to reset counter to initial value in descendant div and continue with that counter from that new value in another div, then I have a problem.

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.

Because of that I assume that when I reset-counter by some heading, new counter is set just for the div where that heading is and its descendants. So in next div no counter has been set and counting starts from beginning. Solution may be not to reset counter, but to set counter to initial value. But I haven't found way to do this. Is is possible? Or I have to use javascript for this way of using numbered headings? Or is there another solution?

.text-container {
    counter-reset: section sub-section composite;
    h1.numbered {
        counter-reset: sub-section;
    }
    h2.numbered {
        counter-reset: composite;
    }
}

h1.numbered:before {
    counter-increment: section;
    content: counter(section) " ";
}
h2.numbered:before {
    counter-increment: sub-section;
    content: counter(section) "." counter(sub-section) " ";
}
h3.numbered:before {
    counter-increment: composite;
    content: counter(section) "." counter(sub-section) "." counter(composite) " ";
}
<div class="text-container">
  <div class="text-section">
    <div class="text-section-column">
      <h1 class="numbered">result 1 Heading</h1>
      <h2 class="numbered">result 1.1 Heading</h2>
    </div>
    <div class="text-section-column">
      <h3 class="numbered">result 1.1.1 Heading</h3>
      <h2 class="numbered">result 1.2 Heading</h2>
      <h3 class="numbered">result 1.2.1 Heading</h3>
    </div>
  </div>
  <div class="text-section">
    <div class="text-section-column">
      <h3 class="numbered">result 1.2.1 Heading (expected 1.2.2)</h3>
    </div>
  </div>
</div>

In third .text-section-column I want counting to continue from last value, but new counter is set.

Thanks.

Upvotes: 3

Views: 1213

Answers (1)

tao
tao

Reputation: 90068

Updated answer:

According to spec:

Counters are "self-nesting", in the sense that resetting a counter in a descendant element or pseudo-element automatically creates a new instance of the counter.

..., which means nesting will affect your arbitrary nested counters.

So you have two options:

A. Don't nest at all:

.numbered:before { color: red; }

.text-container {
    counter-reset: a b 1 c;
}

h1.numbered {
  counter-increment: a;
  counter-reset: b;
}
h2.numbered {
  counter-increment: b;
  counter-reset: c;
}
h3.numbered {
  counter-increment: c;
}
h1.numbered:before {
  content: counter(a) " ";
}
h2.numbered:before {
    content: counter(a) "." counter(b) " ";
}
h3.numbered:before {
    content: counter(a) "." counter(b) "." counter(c) " ";
}
<div class="text-container">
  <div class="text-section">
    <div class="text-section-column">
      <h1 class="numbered">result 1 Heading</h1>
      <h2 class="numbered">result 1.1 Heading</h2>
      <h3 class="numbered">result 1.1.1 Heading</h3>
      <h2 class="numbered">result 1.2 Heading</h2>
      <h3 class="numbered">result 1.2.1 Heading</h3>
      <h3 class="numbered">result <strike>1.2.1</strike> 1.2.2 Heading (expected 1.2.2)</h3>
    </div>
  </div>
</div>

B. Or, if you nest, do it properly:

.numbered:before { color: red; }

.item {
 counter-increment: item; 
}
.item > .item {
  counter-reset: item;
}
.item ~ .item {
  counter-reset: none;
}
.item .numbered::before {
   content: counters(item, ".") " ";
}
<div class="text-container">
  <div class="item">
    <h1 class="numbered">result 1 Heading</h1>
    <div class="item">
      <h2 class="numbered">result 1.1 Heading</h2>
      <div class="item">
        <h3 class="numbered">result 1.1.1 Heading</h3>
      </div>
      <div class="item">
        <h3 class="numbered">result 1.1.2 Heading</h3>
      </div>
    </div>
    <div class="item">
      <h2 class="numbered">result 1.2 Heading</h2>
      <div class="item">
        <h3 class="numbered">result 1.2.1 Heading</h3>
      </div>
      <div class="item">
        <h3 class="numbered">result <strike>1.2.1</strike> 1.2.2 Heading (expected 1.2.2)</h3>
      </div>
    </div>
  </div>
</div>


Initial answer:

I'm assuming you're looking for this?

.numbered:before { color: red; }

.text-container {
    counter-reset: a b 1 c;
}

h1.numbered {
  counter-increment: a;
  counter-reset: b;
}
h2.numbered {
  counter-increment: b;
  counter-reset: c;
}
h3.numbered {
  counter-increment: c;
}
h1.numbered:before {
  content: counter(a) " ";
}
h2.numbered:before {
    content: counter(a) "." counter(b) " ";
}
h3.numbered:before {
    content: counter(a) "." counter(b) "." counter(c) " ";
}
<div class="text-container">
  <div class="text-section">
    <div class="text-section-column">
      <h1 class="numbered">result 1 Heading</h1>
      <h2 class="numbered">result 1.1 Heading</h2>
    </div>
    <div class="text-section-column">
      <h3 class="numbered">result 1.1.1 Heading</h3>
      <h2 class="numbered">result 1.2 Heading</h2>
      <h3 class="numbered">result 1.2.1 Heading</h3>
    </div>
  </div>
  <div class="text-section">
    <div class="text-section-column">
      <h3 class="numbered">result <strike>1.2.1</strike> 1.2.2 Heading (expected 1.2.2)</h3>
    </div>
  </div>
</div>

Upvotes: 3

Related Questions