CSS Counters
Automatic numbering and counting with pure CSS
🔢 What are CSS Counters?
CSS counters allow you to automatically number elements and create sophisticated numbering systems without JavaScript. Perfect for creating numbered lists, chapters, steps, and more.
/* Initialize a counter */
.container {
counter-reset: step-counter;
}
/* Increment and display counter */
.step {
counter-increment: step-counter;
}
.step::before {
content: "Step " counter(step-counter) ": ";
font-weight: bold;
color: #3b82f6;
}
Output:
Counter Properties
counter-reset
Initialize or reset a counter
.container {
counter-reset: my-counter 0;
}
counter-increment
Increase counter value
.item {
counter-increment: my-counter 1;
}
counter()
Display counter value
.item::before {
content: counter(my-counter);
}
counters()
Nested counter display
.nested::before {
content: counters(section, ".");
}
🔹 Advanced Counter Styling
CSS counters enable automatic numbering and custom list styling beyond default ordered lists, offering advanced typographic control. Using properties like counter-reset, counter-increment, and content: counter(), you can create custom numbered headings, step-by-step tutorials, or complex legal documents. Counters are fully styleable with fonts, colors, and positioning, allowing seamless integration with design systems. This technique reduces manual numbering, ensures consistency, and enhances content readability. Well-structured numbered content improves user engagement and retention, which are positive SEO signals. Additionally, semantic use of counters supports accessibility and content hierarchy, further boosting SEO through better content organization.
/* Modern chapter numbering */
:root {
--primary-color: #6366f1;
--secondary-color: #f1f5f9;
--text-color: #334155;
}
.book {
counter-reset: chapter-counter;
max-width: 800px;
margin: 0 auto;
font-family: 'Inter', sans-serif;
}
.chapter {
counter-increment: chapter-counter;
margin: 2rem 0;
padding: 2rem;
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.chapter::before {
content: "Chapter " counter(chapter-counter);
position: absolute;
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, var(--primary-color), #8b5cf6);
color: white;
padding: 1rem 2rem;
font-weight: 600;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.chapter-title {
margin-top: 3rem;
margin-bottom: 1rem;
font-size: 1.5rem;
font-weight: 700;
color: var(--text-color);
}
/* Nested section numbering */
.chapter {
counter-reset: section-counter;
}
.section {
counter-increment: section-counter;
margin: 1.5rem 0;
padding-left: 2rem;
position: relative;
}
.section::before {
content: counter(chapter-counter) "." counter(section-counter);
position: absolute;
left: 0;
top: 0;
width: 1.5rem;
height: 1.5rem;
background: var(--primary-color);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
}
Output:
Introduction to Web Development
Advanced CSS Techniques
🔹 Modern Counter Examples
Modern CSS counters are used creatively for dynamic numbering in tutorials, documentation, multi-level lists, and interactive components. Examples include custom-styled step counters in how-to guides, nested legal clause numbering, and pagination indicators in galleries. With CSS Grid and Flexbox integration, counters adapt responsively across devices. They also pair with pseudo-elements like ::before for polished typography. This approach eliminates hard-coded numbers, making content easier to update and scale. For SEO, dynamic and well-structured numbered content improves readability, reduces bounce rates, and increases time-on-page—all key user engagement metrics that search engines consider when ranking pages.
/* Modern progress steps */
.progress {
counter-reset: step;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 1rem;
padding: 1.5rem;
background: #f8f9fa;
border-radius: 16px;
}
.step {
counter-increment: step;
position: relative;
padding: 1.25rem;
background: white;
border-radius: 12px;
text-align: center;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
transition: transform 0.2s;
}
.step:hover {
transform: translateY(-2px);
}
.step::before {
content: counter(step);
position: absolute;
top: -0.75rem;
left: 50%;
transform: translateX(-50%);
width: 1.75rem;
height: 1.75rem;
background: #6366f1;
color: white;
border-radius: 8px;
display: grid;
place-items: center;
font-weight: 600;
font-size: 0.875rem;
}
/* Modern FAQ */
.faq {
counter-reset: faq;
max-width: 600px;
margin: 2rem auto;
display: grid;
gap: 1rem;
}
.faq-item {
counter-increment: faq;
background: white;
border-radius: 12px;
padding: 1rem 1rem 1rem 3rem;
position: relative;
box-shadow: 0 2px 4px rgb(0 0 0 / 0.05);
}
.faq-item::before {
content: "Q" counter(faq);
position: absolute;
left: 1rem;
color: #6366f1;
font-weight: 600;
}