Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong numbering with css counters

Tags:

html

css

Why the following css doesn't get correct numbering of sections (http://jsfiddle.net/75MHS/)? When I put h3 and h4 inside divs, all chapter numbers and section numbers are always one. But when I remove div containers, the numbers are all correct.

<!DOCTYPE html>
<html>
<head>
<style type='text/css'>
h3 {
  counter-increment: chapter;
  counter-reset: section;
}
h3:before {
  content: "Chapter " counter(chapter) " ";
}
h4 {
  counter-increment: section;
}
h4:before {
  content: counter(section) " ";
}
</style>
</head>
<body>
<!-- wrong counter -->
<div><h3>dddd</h3></div>
<div><h4>dddd</h4></div>
<div><h4>dddd</h4></div>
<div><h3>dddd</h3></div>
<div><h4>dddd</h4></div>
<div><h4>dddd</h4></div>

<!-- correct counter -->
<!--
<h3>dddd</h3>
<h4>dddd</h4>
<h4>dddd</h4>
<h3>dddd</h3>
<h4>dddd</h4>
<h4>dddd</h4>
-->
</body>
</html>
like image 746
Z.H. Avatar asked Dec 30 '13 12:12

Z.H.


2 Answers

The reason it works as intended in the second section (without the div's) but doesn't in the fist section is due to counter scope. According to the W3C:

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.

In the second half of the html, the h3s and h4s are siblings, therefore, the counter-reset defined on the h3 applies to the following h4 siblings. In the first part of the html, the h4s are not descendants nor siblings of the h3s, therefore, the counter-rest has no effect on them since they're out of scope.

The other thing is, if counter-reset is not defined in a given scope, it assumes a value of 0 each time you counter-increment or refer to the counter in a content rule, which explains why you're getting all 1s in the first part of the html:

If 'counter-increment' or 'content' on an element or pseudo-element refers to a counter that is not in the scope of any 'counter-reset', implementations should behave as though a 'counter-reset' had reset the counter to 0 on that element or pseudo-element.


If you have to wrap things in divs, I would:

  1. Define a counter-reset for the chapters counter on body, so that it's not assumed 0 each time you use a counter-increment.

  2. Either nest the h4s under their parent h3s (which is not cool) or make them siblings to ensure they're in the right scope.


New HTML:

<div>
    <h3>dddd</h3>
    <h4>dddd</h4>
    <h4>dddd</h4>
</div>
<div>
    <h3>dddd</h3>
    <h4>dddd</h4>
    <h4>dddd</h4>
</div>

Addition to CSS:

body {
    counter-reset: chapter;
}

http://jsfiddle.net/myajouri/QpG9d/

like image 188
myajouri Avatar answered Oct 05 '22 08:10

myajouri


You are forgetting that the divs are part of the DOM tree now, you either target them as well or you remove them.

div {
    counter-increment: chapter;
    counter-reset: section;
}
div:before {
    content: "Chapter " counter(chapter) " ";
}
like image 41
Adonis K. Kakoulidis Avatar answered Oct 05 '22 09:10

Adonis K. Kakoulidis