Reputation: 665
I have this kink of code, where HTML is generated by hieroglyph, and CSS is provided by me:
<html>
<head>
<style>
body {
counter-reset: chapter 3 section 0;
}
h2 {
counter-reset: slide 0;
counter-increment: section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter) ". ";
}
h2:before {
content: counter(chapter) "." counter(section) " ";
}
h3:before {
content: counter(chapter) "." counter(section) "." counter(slide) " ";
}
</style>
</head>
<body>
<article> <h1>chapter</h1> </article>
<article> <h2>section A</h2> </article>
<article> <h3> slide a</h3> </article>
<article> <h3> slide b</h3> </article>
<article> <h2>section B</h2> </article>
<article> <h3> slide a</h3> </article>
<article> <h3> slide b</h3> </article>
</body>
</html>
I would like to number h1/h2/h3 (which I name chapter, section, slide), but
article
tag make it difficult.
How can I fix the CSS rules, in order to see:
3. chapter
3.1 section A
3.1.1 side a
3.1.2 side b
3.2 section B
3.2.1 side a
3.2.2 side b
Instead of (h3
are wrongly numbered):
3. chapter
3.1 section A
3.1.1 side a
3.1.1 side b
3.2 section B
3.2.1 side a
3.2.1 side b
Upvotes: 2
Views: 2504
Reputation: 1
I've been needing this question to validate a list in a pdf, however I had difficulty using it the way it was made available here, since as the h1 was not implemented in the css it does not count. Anyway, there is a solution that I adapted for myself.
<!DOCTYPE html>
<html>
<head>
<style>
body {
counter-reset: chapter 0 section 0;
}
h1{
counter-increment: chapter;
}
h2 {
counter-reset: slide 0;
counter-increment: section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>This paragraph is styled with CSS.</p>
<h2>Test</h2>
<p>CSS comments are not shown in the output.</p>
<h1>Hello World!</h1>
<p>This paragraph is styled with CSS.</p>
</body>
</html>
Upvotes: 0
Reputation: 89750
Reasons:
As I had described in my comment to the question, CSS counters are very sensitive to levels and the document structure. If the structure doesn't match a certain pattern then it will affect the entire working of the counters. This is because of how elements inherit the counters and the counter's value. Details about how the counters work, how they are inherited is described in my answer here.
For the sake of more clarity, I have added inline comments in the below snippet to explain the working:
body {
counter-reset: chapter 3 section 0;
}
h2 {
counter-reset: slide 0;
counter-increment: section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
<!-- body creates chapter, section counters -->
<article> <!-- this inherits both counters from its parent and also its value because it is the previous element in document order -->
<h1>chapter</h1> <!-- inherits both counters and their value from parent -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h2>section A</h2> <!-- inherits both counters, increments section to 1, creates slide counter. slide counter is visible only to this element but not parent -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h3> slide a</h3> <!-- inherits chapter, section but sees no slide counter and hence creates a new slide counter and increments to 1, the parent doesn't know about this new slide counter -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h3> slide b</h3> <!-- inherits chapter, section but sees no slide counter and hence creates a new slide counter and increments to 1, the parent doesn't know about this new slide counter -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h2>section B</h2> <!-- inherits both counters, increments section to 2, creates slide counter. slide counter is visible only to this element but not parent -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h3> slide a</h3> <!-- inherits chapter, section but sees no slide counter and hence creates a new slide counter and increments to 1, the parent doesn't know about this new slide counter -->
</article>
<article> <!-- this inherits both chapter and section counters from parent (body) and the value for the counters from the previous sibling -->
<h3> slide b</h3> <!-- inherits chapter, section but sees no slide counter and hence creates a new slide counter and increments to 1, the parent doesn't know about this new slide counter -->
</article>
However the solution described in the linked thread would still not work for this case because of how the document is structured. Even if we reset the slide
counter at body and make the counter visible to all child elements, the reset to 0 happens only when a h2
is encountered. Since all h2
are inside their respective article
and the article
(and thereby the child h2
) already have slide
counter inherited from their parent, another reset at a different level possibly results in self nesting (that is, new slide
counter being created nested under the parent slide
). Because of it, subsequent reset have no effect and the h3
elements keep continuing the numbering as seen in the below snippet:
body {
counter-reset: chapter 3 section 0 slide 0;
}
h2 {
counter-reset: slide 0;
counter-increment: section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
<article>
<h1>chapter</h1>
</article>
<article>
<h2>section A</h2>
</article>
<article>
<h3> slide a</h3>
</article>
<article>
<h3> slide b</h3>
</article>
<article>
<h2>section B</h2>
</article>
<article>
<h3> slide a</h3>
</article>
<article>
<h3> slide b</h3>
</article>
Solution:
There are three solutions to this situation and they are as follows:
Change the document structure to have the h3
elements grouped under the same article
like in the below snippet.
body {
counter-reset: chapter 3 section 0;
}
h2 {
counter-reset: slide 0;
counter-increment: section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
<article>
<h1>chapter</h1>
</article>
<article>
<h2>section A</h2> <!-- The reset here has no effect because it creates a different instance -->
</article>
<article>
<h3> slide a</h3> <!-- Parent doesn't have slide counter, so this creates one and increments it to 1 -->
<h3> slide b</h3> <!-- This inherits slide counter's value fom previous element and increments to 2 -->
</article>
<article>
<h2>section A</h2> <!-- The reset here has no effect because it creates a different instance -->
</article>
<article>
<h3> slide a</h3> <!-- Parent doesn't have slide counter, so this creates one and increments it to 1 -->
<h3> slide b</h3> <!-- This inherits slide counter's value fom previous element and increments to 2 -->
</article>
Give each article
a class which indicates what it contains and then do the counter-reset
or counter-increment
at the parent level itself. This means the counters and their values would be visible to all siblings. This in my opinion is the best approach without modifying your structure.
.h1-container {
counter-reset: chapter 3 section 0 slide 0;
}
.h2-container {
counter-reset: slide 0;
counter-increment: section;
}
.h3-container {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
<article class='h1-container'>
<h1>chapter</h1>
</article>
<article class='h2-container'>
<h2>section A</h2>
</article>
<article class='h3-container'>
<h3> slide a</h3>
</article>
<article class='h3-container'>
<h3> slide b</h3>
</article>
<article class='h2-container'>
<h2>section A</h2>
</article>
<article class='h3-container'>
<h3> slide a</h3>
</article>
<article class='h3-container'>
<h3> slide b</h3>
</article>
Use JavaScript or jQuery (or other preferred libraries) to count the elements and set numbering according to it.
Upvotes: 1
Reputation: 46579
How about this. No JavaScript; HTML markup the same as you had originally.
body {
counter-reset: chapter 3 section 0 slide 2;
}
h2 {
counter-increment: slide -2 section;
}
h3 {
counter-increment: slide;
}
h1:before {
content: counter(chapter)". ";
}
h2:before {
content: counter(chapter)"." counter(section)" ";
}
h3:before {
content: counter(chapter)"." counter(section)"." counter(slide)" ";
}
<article> <h1>chapter</h1> </article>
<article> <h2>section A</h2> </article>
<article> <h3> slide a</h3> </article>
<article> <h3> slide b</h3> </article>
<article> <h2>section B</h2> </article>
<article> <h3> slide a</h3> </article>
<article> <h3> slide b</h3> </article>
It works by not doing a counter-reset
, but a counter-increment
for the slide
counter, thus keeping the counter global. However, there's a catch: it works only when the number of slides is fixed (in this case, 2).
Upvotes: 0