CSS Counters
CSS counters are simple integer values maintained by the browser that you can increment, reset, and print inside ::before
/::after
(or content
) to generate automatic numbering for headings, custom list markers, callouts, etc. They’re great when you want visual numbering separate from document markup.
Basic concepts / properties
counter-reset: name [value]
— creates or resets a counter (default value 0).counter-increment: name [value]
— increases the counter (default increment 1).content: counter(name)
— inserts the counter value (string).counters(name, "sep")
— returns a list of counter values joined bysep
(useful for hierarchical numbers).counter-set
(newer) — sets a counter to a specific value (not supported everywhere; use carefully).
Numbered Sections with Headings
Instead of writing numbers manually in your <h2>
headings, you can let CSS handle it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Counters - Numbered Sections</title>
<style>
article {
counter-reset: section; /* initialize counter */
}
article h2 {
counter-increment: section; /* increase counter on each h2 */
position: relative;
padding-left: 2.2rem;
}
article h2::before {
content: counter(section) ". "; /* print number */
position: absolute;
left: 0;
font-weight: bold;
color: #0077cc;
}
</style>
</head>
<body>
<article>
<h2>Introduction</h2>
<p>This is the introduction section.</p>
<h2>Getting Started</h2>
<p>Steps to begin with CSS counters.</p>
<h2>Advanced Usage</h2>
<p>How to use nested counters and custom styles.</p>
</article>
</body>
</html>
Output :
Nested Numbering (1.1, 1.2, 2.1)
Perfect for documents, eBooks, or multi-level tutorials.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Counters - Nested Numbering</title>
<style>
article {
counter-reset: section;
}
article h2 {
counter-increment: section;
counter-reset: subsection;
}
article h2::before {
content: counter(section) ". ";
font-weight: bold;
color: #e67e22;
}
article h3 {
counter-increment: subsection;
margin-left: 1.5rem;
}
article h3::before {
content: counter(section) "." counter(subsection) " ";
color: #666;
}
</style>
</head>
<body>
<article>
<h2>Chapter One</h2>
<h3>Subsection A</h3>
<h3>Subsection B</h3>
<h2>Chapter Two</h2>
<h3>Subsection A</h3>
</article>
</body>
</html>
Output :
Custom Lists (Roman Numerals & Alphabets)
You can style lists with counters instead of using <ol>
default styling.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Counters - Custom List</title>
<style>
ul.custom {
list-style: none;
counter-reset: mylist;
padding-left: 1.5rem;
}
ul.custom li {
counter-increment: mylist;
margin: .5rem 0;
position: relative;
}
ul.custom li::before {
content: counter(mylist, upper-roman) ". "; /* I, II, III */
position: absolute;
left: -1.5rem;
font-weight: bold;
color: #2ecc71;
}
</style>
</head>
<body>
<ul class="custom">
<li>Introduction</li>
<li>Setup Environment</li>
<li>Learn CSS Basics</li>
</ul>
</body>
</html>
Output :