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:

Create your HTML structure
Add CSS styling
Test your website
Deploy to production

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

HTML Fundamentals
CSS Basics
JavaScript Introduction

Advanced CSS Techniques

Flexbox Layout
CSS Grid
Animations

🔹 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;
}

Output:

Plan
Design
Build
Test
What are CSS counters?
How do I reset a counter?
Can I use multiple counters?

🧠 Test Your Knowledge

Which property is used to initialize a CSS counter?