category | cover | created | tags | title |
---|---|---|---|---|
Tip |
/assets/tips/number-headings-subheadings.png |
2021-03-14 |
CSS |
Number headings and subheadings automatically |
It's a common approach to use the DOM APIs to find all headings on the page, and number each of them. This post introduces another way to do that with CSS only.
If you follow some search engine optimization (known as SEO) practices, you are adviced to use only one h1
tag on the page. The single h1
tag is used to display the main title. Hence, we will ignore the h1
tag when numbering the headings.
Given the following markup:
<h2>Chapter 1</h2>
<h3>Section 1</h3>
<h4>Sub section A</h4>
<h3>Section 2</h3>
<h4>Sub section A</h4>
<h4>Sub section B</h4>
<h2>Chapter 2</h2>
It should produce the content as below:
1. Chapter 1
1.1. Section 1
1.1.1. Sub section A
1.2. Section 2
1.2.1. Sub section A
1.2.2. Sub section B
2. Chapter 2
We can archive it by using the CSS counter.
Going down from the body
element, we will reset the counter for the first h2
. The numbers are inserted before the content via the ::before
pseudo element:
body,
h1 {
counter-reset: h2;
}
h2::before {
counter-increment: h2;
content: counter(h2) '. ';
}
The counter-increment
property indicates that when we see the next h2
tag, the number will be increased by one.
We continue using the same technique for h3
tags. The number for a h3
heading must be prefixed with the number of its parent h2
tag:
h2 {
counter-reset: h3;
}
h3::before {
counter-increment: h3;
content: counter(h2) '.' counter(h3) '. ';
}
Here we use the .
character to separate the numbers. If you want to number deeper headings such as h4
, h5
, then the CSS should look like as following:
h3 {
counter-reset: h4;
}
h4 {
counter-reset: h5;
}
h4::before {
counter-increment: h4;
content: counter(h2) '.' counter(h3) '.' counter(h4) '. ';
}
h5::before {
counter-increment: h5;
content: counter(h2) '.' counter(h3) '.' counter(h4) '.' counter(h5) '. ';
}