Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to number headings automatically

Short answer

Create a counter on the wrapper, increment it on every heading and print it with ::before:

<style>
  .doc { counter-reset: chapter; }
  .doc h2 { counter-increment: chapter; font-size: 18px; }
  .doc h2::before { content: counter(chapter) ". "; color: tomato; }
</style>
 
<div class="doc">
  <h2>Getting started</h2>
  <h2>Installation</h2>
  <h2>First project</h2>
</div>

counter-reset creates a counter with the value 0, counter-increment adds one, and counter() puts the current value into content. When you add or remove a heading, the numbers update by themselves.

Nested numbering 1.1, 1.2

A second counter is reset on every <h2>, so the subsections of each chapter start from one:

<style>
  .doc { counter-reset: chapter; }
  .doc h2 { counter-increment: chapter; counter-reset: section; font-size: 18px; }
  .doc h3 { counter-increment: section; font-size: 15px; margin-left: 16px; }
  .doc h2::before { content: counter(chapter) ". "; }
  .doc h3::before { content: counter(chapter) "." counter(section) " "; }
</style>
 
<div class="doc">
  <h2>Layout</h2>
  <h3>Flexbox</h3>
  <h3>Grid</h3>
  <h2>Colors</h2>
  <h3>Gradients</h3>
</div>

A different number style

As a second argument counter() takes a list style: counter(chapter, upper-roman) gives I, II, III, and counter(chapter, lower-alpha) gives a, b, c.

Common mistake

Writing counter-reset on the heading itself instead of the common parent. Then every heading creates its counter anew, and they all get the number 1. Reset the counter on the element that contains all the numbered headings, and for a nested level — on the heading one level up.

Functions used in this recipe

  • counter-reset — `counter-reset` creates a CSS counter (or resets it), `counter-increment` increases it on each matching element; the value is printed with `counter()`.
  • counter() — Prints the value of a CSS counter in `content`; `counters()` prints all nested levels at once, like 2.1.3.
  • content — The content of the `::before` and `::after` pseudo-elements.
  • ::before — Creates a virtual first child of the element — for decorative text or shapes.

Thanks for reading!

Donate to the site — we work hard for you.