CSS counter() Function

The CSS counter() function returns the current value of a named CSS counter as a formatted string.

It is commonly used with the content, counter-reset, and counter-increment properties to create automatic numbering for lists, headings, steps, and other generated content. Counter values update automatically when elements are added or removed.

Syntax

counter(name)
counter(name, style)

The counter() function accepts the name of a CSS counter and an optional counter style.

For example:

.item::before {
  content: counter(section);
}

This inserts the current value of the counter named section before the element's content.

Additional examples:

content: counter(section);
content: counter(section, decimal);
content: counter(section, upper-roman);
content: counter(section, lower-alpha);
content: "Step " counter(step) ": ";
content: counter(chapter) "." counter(section);

The function produces text representing the counter value. It does not create, reset, or increment the counter.

Those operations are handled by separate CSS properties.

Parameters

The counter() function accepts one required parameter and one optional parameter.

Parameter Description
name The name of the CSS counter whose current value should be displayed. This is a case-sensitive identifier.
style An optional counter style that controls how the number is displayed, such as decimal, upper-roman, or lower-alpha.

If the style is omitted, the function uses decimal numbering.

For example:

counter(item)
counter(item, decimal)

Both display the same decimal counter value.

The following uses uppercase Roman numerals:

counter(item, upper-roman)

A counter value of 4 would be displayed as IV.

The function accepts a counter style name, including a custom style defined with @counter-style, or a supported symbols() expression.

How It Works

CSS counters work by maintaining numeric values that can be reset, incremented, and displayed.

A typical counter uses three steps:

  1. Create a counter using counter-reset.
  2. Increase its value using counter-increment.
  3. Display its value using counter() in generated content.

For example:

.steps {
  counter-reset: step;
}
.steps p {
  counter-increment: step;
}
.steps p::before {
  content: counter(step) ". ";
}

With the following HTML:

<div class="steps">
  <p>Create the HTML file</p>
  <p>Add the CSS styles</p>
  <p>Preview the result</p>
</div>

The generated content displays:

1. Create the HTML file
2. Add the CSS styles
3. Preview the result

Each paragraph increments the counter before its ::before pseudo-element displays the current value.

If another paragraph is added, its number is generated automatically.

Counter Properties

Several CSS properties control how counters are created and updated.

Property Purpose
counter-reset Creates or resets a counter to a specified starting value.
counter-increment Increases or decreases a counter by a specified integer.
counter-set Sets an existing counter to a specific value or creates it when necessary.
content Displays a formatted counter value in generated content.

For example:

.list {
  counter-reset: item;
}
.list .entry {
  counter-increment: item;
}
.list .entry::before {
  content: counter(item) ". ";
}

The counter-reset property establishes the counter, while counter-increment updates its value for each entry.

The counter() function reads the value at the point where it is used.

To assign a specific value without incrementing:

.special-entry {
  counter-set: item 10;
}

Subsequent counter operations continue from the assigned value.

Counter Styles

The optional second parameter controls how the numeric counter value is formatted.

Style Example for Value 4
decimal4
decimal-leading-zero04
lower-alphad
upper-alphaD
lower-romaniv
upper-romanIV

For example:

.list {
  counter-reset: item;
}
.list p {
  counter-increment: item;
}
.list p::before {
  content: counter(item, upper-roman) ". ";
}

The generated numbering uses Roman numerals instead of decimal numbers.

Custom counter styles can also be defined using @counter-style:

@counter-style custom-letters {
  system: alphabetic;
  symbols: A B C D E;
  suffix: ". ";
}
.item::before {
  content: counter(item, custom-letters) " ";
}

The custom style determines how counter values are represented.

When counter() is used, the style's suffix is not automatically appended. Add any punctuation or spacing explicitly in the content declaration.

Starting Values

By default, counter-reset initializes a counter to zero.

When the first matching element increments it, the displayed value becomes 1.

For example:

.list {
  counter-reset: item;
}
.list p {
  counter-increment: item;
}

To begin displaying numbers at 5, initialize the counter to 4:

.list {
  counter-reset: item 4;
}

The first increment produces 5.

Counters can also decrease:

.countdown {
  counter-reset: remaining 6;
}
.countdown p {
  counter-increment: remaining -1;
}
.countdown p::before {
  content: counter(remaining) ". ";
}

The generated numbers begin at 5 and decrease by one for each paragraph.

To change the amount added for each element:

.list p {
  counter-increment: item 2;
}

This produces values such as 2, 4, 6, and 8 when starting from zero.

Multiple Counters

Multiple named counters can be used together to create numbering systems for chapters, sections, and other document structures.

For example:

.document {
  counter-reset: chapter;
}
.document h2 {
  counter-increment: chapter;
  counter-reset: section;
}
.document h3 {
  counter-increment: section;
}
.document h2::before {
  content: "Chapter " counter(chapter) ": ";
}
.document h3::before {
  content: counter(chapter) "." counter(section) " ";
}

The generated headings can display:

Chapter 1: Introduction
1.1 Getting Started
1.2 Basic Syntax
Chapter 2: CSS Layout
2.1 Flexbox
2.2 Grid

Each named counter maintains its own value.

The section counter is reset when a new chapter begins.

Multiple counter() functions can be combined in one content declaration to display separate counter values.

For nested counter scopes that share the same counter name, the related counters() function can combine values from the counter hierarchy automatically.

Using with Pseudo-Elements

The counter() function is commonly used with the ::before and ::after pseudo-elements.

For example:

.steps {
  counter-reset: step;
}
.steps .step {
  counter-increment: step;
}
.steps .step::before {
  content: "Step " counter(step) ": ";
  font-weight: bold;
}

The generated number appears before the element's existing content.

To display the number after the content:

.steps .step::after {
  content: " (" counter(step) ")";
}

Generated content is controlled by CSS rather than inserted directly into the HTML document.

For meaningful ordered sequences, use semantic HTML such as <ol> and <li> whenever possible.

Example

This example uses counter() to number three steps automatically.

HTML:

<div class="counter-demo">
  <div class="counter-demo-step">Create an HTML document</div>
  <div class="counter-demo-step">Add a CSS stylesheet</div>
  <div class="counter-demo-step">Preview the web page</div>
</div>

CSS:

.counter-demo {
  counter-reset: demo-step;
}
.counter-demo-step {
  counter-increment: demo-step;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  padding: 12px;
  background-color: #f2f5f9;
}
.counter-demo-step::before {
  content: counter(demo-step);
  display: grid;
  place-items: center;
  flex: 0 0 32px;
  height: 32px;
  border-radius: 50%;
  background-color: #0066cc;
  color: #fff;
  font-weight: bold;
}
Browser Result
Create an HTML document
Add a CSS stylesheet
Preview the web page

The numbers are generated automatically. Adding another step increases the sequence without manually editing the numbering.

Heading Numbering Example

The following example numbers headings using uppercase Roman numerals.

HTML:

<div class="counter-heading-demo">
  <h3>Introduction</h3>
  <h3>HTML Structure</h3>
  <h3>CSS Styling</h3>
</div>

CSS:

.counter-heading-demo {
  counter-reset: demo-heading;
}
.counter-heading-demo h3 {
  counter-increment: demo-heading;
  margin-bottom: 12px;
  font-size: 18px;
}
.counter-heading-demo h3::before {
  content: counter(demo-heading, upper-roman) ". ";
  color: #0066cc;
}
Browser Result

Introduction

HTML Structure

CSS Styling

The headings display Roman numeral prefixes I, II, and III.

Changing the style parameter to lower-alpha would display a, b, and c instead.

counter() vs. counters()

The counter() and counters() functions both display CSS counter values, but they handle counter scopes differently.

Function Purpose Example
counter() Displays the value of the innermost counter with the specified name. counter(item)
counters() Combines values from nested counters sharing the same name, using a separator. counters(item, ".")

For example:

content: counter(section);
content: counters(section, ".");

The first displays one counter value. The second can display a hierarchy such as 1.2.3 when nested counter scopes exist.

Use counter() for ordinary sequential numbering and counters() when a nested hierarchy needs to be displayed.

Accessibility

CSS-generated numbering can improve the visual organization of content, but it should not replace meaningful HTML structure.

For ordered lists, use semantic HTML:

<ol>
  <li>Create the HTML document</li>
  <li>Add the CSS stylesheet</li>
  <li>Preview the result</li>
</ol>

Browsers and assistive technologies can recognize the list structure even without CSS.

CSS-generated content may be announced by some screen readers, but its presentation is not consistent across all assistive technologies.

Do not rely on generated counter text as the only source of essential information.

When numbering headings, retain appropriate heading elements such as <h2> and <h3> so the document hierarchy remains meaningful.

Common Uses

The counter() function is useful for automatically numbering repeated content.

Use Description
Numbered steps Automatically number steps in a process or tutorial.
Document headings Add chapter or section numbers to headings.
Custom lists Create numbering styles beyond the default list markers.
Figures and examples Number illustrations, code examples, or other repeated content.
Multi-level numbering Combine different named counters for chapter and section references.
Custom numbering formats Display decimal, alphabetic, Roman numeral, or custom counter styles.

For example, code examples can be numbered automatically:

.examples {
  counter-reset: example;
}
.examples .code-example {
  counter-increment: example;
}
.examples .code-example::before {
  content: "Example " counter(example) ":";
  display: block;
  font-weight: bold;
}

Each code example receives the next number in the sequence.

Limitations

The counter() function has several important rules and limitations.

  • It requires a counter name.
  • The optional second parameter must identify a valid counter style.
  • The function reads a counter value but does not increment or reset it.
  • Counter values depend on CSS counter scope and document order.
  • When a named counter has not been established, its value is treated as zero for the function.
  • Generated numbering does not automatically create semantic list structure.
  • The function returns formatted text rather than a numeric value for calculations.
  • Nested counters sharing one name require counters() to display their complete hierarchy.

For example, this is valid:

content: counter(item);

However, the following is invalid because the counter name is missing:

content: counter();

The following is also invalid because counter() does not accept a separator parameter:

content: counter(item, decimal, ".");

Use counters() when a separator is needed between values from nested counters.

Browser Support

The CSS counter() function is Baseline Widely available and has been supported across major browsers for many years.

Basic counter numbering works in current versions of Chrome, Edge, Firefox, Safari, and other modern browsers.

For a fallback, ensure that essential numbering and list relationships are represented in the HTML when they are necessary to understand the content.

For example, standard ordered lists provide native numbering:

<ol>
  <li>First step</li>
  <li>Second step</li>
  <li>Third step</li>
</ol>

For current compatibility information, visit Can I Use? .

Specifications

The counter() function is defined in the CSS Lists and Counters Module Level 3 .

The specification defines counter functions, counter values, formatting, and their relationship to counter scopes.

Related features include counters(), symbols(), counter-reset, counter-increment, counter-set, and @counter-style.