CSS Auto Heading Numbering

CSS Auto Heading Numbering

CSS counters provide a powerful way to automatically number headings in HTML documents without JavaScript or manual updates. This technique uses the counter-reset and counter-increment properties to create hierarchical numbering, such as 1., 1.1., 1.1.1., and so on. In this demo, we apply counters to h2 through h6 elements, resetting at each level for proper nesting. An optional “nocount” class allows skipping numbering for specific headings, maintaining continuity. This approach ensures consistent, dynamic numbering that updates automatically as content changes.

How CSS Counters Work for Headings

CSS counters are a feature that lets you increment and display numerical values based on elements in the DOM. For headings, we reset a counter at the start of each level and increment it before each heading, using the :before pseudo-element to prepend the number.

The code sets up counters for h2 to h6:

body {
  counter-reset: h2;
}

h2 {
  counter-reset: h3;
}

h3 {
  counter-reset: h4;
}

h4 {
  counter-reset: h5;
}

h5 {
  counter-reset: h6;
}

Each heading level resets the next lower level’s counter. Then, we increment and display:

h2:before {
  counter-increment: h2;
  content: counter(h2) ". ";
}

h3:before {
  counter-increment: h3;
  content: counter(h2) "." counter(h3) ". ";
}

This creates nested numbering. For example, the first h2 is “1.”, its first h3 is “1.1.”, and so on.

To skip numbering, add a class:

h2.nocount:before,
h3.nocount:before,
h4.nocount:before,
h5.nocount:before,
h6.nocount:before {
  content: "";
  counter-increment: none;
}

In the HTML, headings like <h3 class="nocount">Heading three e no count</h3> won’t be numbered, but subsequent ones continue the count.

Example Output

Applying this to sample HTML:

<h1>Heading One</h1>
<h2>Heading two a</h2>
<h3>Heading three a</h3>
<h3>Heading three b</h3>
<h2>heading two b</h2>
<h3>Heading three c</h3>
<h3>Heading three d</h3>
<h4>Heading 4 A</h4>
<h3 class="nocount">Heading three e no count</h3>
<h3>Heading three f count continue</h3>

Results in numbered headings like:

    1. Heading two a
    • 1.1. Heading three a
    • 1.2. Heading three b
    1. heading two b
    • 2.1. Heading three c
    • 2.2. Heading three d
      • 2.2.1. Heading 4 A
    • Heading three e no count (no number)
    • 2.3. Heading three f count continue

Other Uses for CSS Counters

Beyond headings, CSS counters can be used in various document and web contexts:

  • Outlines and Tables of Contents: Automatically number sections in generated TOCs.
  • Legal Documents: Number clauses, subsections, or footnotes hierarchically.
  • Lists and Steps: For ordered lists with custom numbering, like Roman numerals or letters.
  • Code Comments or Documentation: Number steps in tutorials or API references.
  • Print Stylesheets: Enhance printed documents with automatic page or section numbering.
  • Dynamic Content: In CMS-generated pages where content structure changes frequently.

This pure CSS solution avoids JavaScript dependencies, making it lightweight and performant. It’s especially useful in static sites or when content is authored in Markdown/HTML without preprocessing.

Benefits and Considerations

The main advantage is automatic updates—no need to renumber manually when inserting or removing sections. It works across browsers supporting CSS counters (IE8+). However, screen readers may not announce the numbers, so consider accessibility with ARIA labels if needed. For complex documents, combine with CSS for styling the numbers (e.g., bold or colored).

This demo showcases a simple yet effective way to add structure to web content using native CSS features.