CSS Counters
CSS Counters
CSS counters let you automatically number elements using CSS. They are useful for creating numbered headings, steps, lists, and nested numbering without manually writing the numbers in HTML.
Counters work with three main parts: counter-reset, counter-increment, and content with counter().
Counters
To use a counter, first reset it on a parent element, then increment it on each item, and finally display it using a pseudo-element.
.steps {
counter-reset: step;
}
.steps li {
counter-increment: step;
}
.steps li::before {
content: counter(step) ". ";
font-weight: bold;
}
Example HTML:
<ol class="steps"> <li>Install the tools</li> <li>Create a project</li> <li>Write your CSS</li> </ol>
Counter Styling
You can style the counter output like a badge.
.steps {
counter-reset: step;
list-style: none;
padding: 0;
margin: 0;
max-width: 520px;
}
.steps li {
counter-increment: step;
padding: 12px 12px 12px 52px;
border: 1px solid #eee;
border-radius: 12px;
margin-bottom: 10px;
position: relative;
}
.steps li::before {
content: counter(step);
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
border-radius: 999px;
border: 1px solid #d6e4ff;
background: #f3f6ff;
font-weight: bold;
font-size: 13px;
}
Nested Counters
Nested counters are useful for numbering sections like 1, 1.1, 1.2, 2, 2.1, etc.
Reset the inner counter inside each parent item, then increment both levels as needed.
.outline {
counter-reset: section;
list-style: none;
padding: 0;
margin: 0;
}
.outline > li {
counter-increment: section;
margin-bottom: 10px;
}
.outline > li::before {
content: counter(section) ". ";
font-weight: bold;
}
.outline ul {
counter-reset: sub;
list-style: none;
padding-left: 22px;
margin: 8px 0 0;
}
.outline ul li {
counter-increment: sub;
margin-bottom: 6px;
}
.outline ul li::before {
content: counter(section) "." counter(sub) " ";
color: #555;
font-weight: 600;
}
Example HTML:
<ul class="outline">
<li>Getting Started
<ul>
<li>Install</li>
<li>First Page</li>
</ul>
</li>
<li>Basics
<ul>
<li>Selectors</li>
<li>Box Model</li>
</ul>
</li>
</ul>
Code Challenge
Goal: Build a numbered “steps” list using CSS counters, and add a nested outline using nested counters.
HTML:
<ol class="steps">
<li>Plan the layout</li>
<li>Write the CSS</li>
<li>Test on mobile</li>
</ol>
<ul class="outline">
<li>Section
<ul>
<li>Sub item</li>
<li>Sub item</li>
</ul>
</li>
</ul>
Task:
- Remove default list styles
- Use
counter-resetandcounter-incrementto number items - Use
::beforeandcontentto display the counter - Create nested numbering like 1.1, 1.2 using two counters
Try a Solution:
.steps {
counter-reset: step;
list-style: none;
padding: 0;
margin: 0 0 18px;
max-width: 520px;
}
.steps li {
counter-increment: step;
padding: 12px 12px 12px 52px;
border: 1px solid #eee;
border-radius: 12px;
margin-bottom: 10px;
position: relative;
}
.steps li::before {
content: counter(step);
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
border-radius: 999px;
border: 1px solid #d6e4ff;
background: #f3f6ff;
font-weight: bold;
font-size: 13px;
}
.outline {
counter-reset: section;
list-style: none;
padding: 0;
margin: 0;
}
.outline > li {
counter-increment: section;
margin-bottom: 10px;
}
.outline > li::before {
content: counter(section) ". ";
font-weight: bold;
}
.outline ul {
counter-reset: sub;
list-style: none;
padding-left: 22px;
margin: 8px 0 0;
}
.outline ul li {
counter-increment: sub;
margin-bottom: 6px;
}
.outline ul li::before {
content: counter(section) "." counter(sub) " ";
color: #555;
font-weight: 600;
}
What’s Next?
Next, you will learn CSS units such as px, %, em, rem, vw, and vh.