How to Display an Ordered List with Nested Counters?

A list is a record of short pieces of related information used to display data or any information in web pages in an ordered or unordered form. Lists are used to group related pieces of information together so that they are clearly associated with one another and easy to read. They are beneficial from a structural point of view because they aid in the creation of a well-structured, more accessible, and easy-to-maintain document.

HTML lists enable web developers to organize a collection of related items into lists. There are three types of lists in HTML, each with its own function and meaning.

  • Unordered list ? A collection of related items that are not arranged in any particular order.

  • Ordered list ? A collection of related items that are arranged in any particular order.

  • Description list ? A list of terms and their descriptions.

When we need to display nested counters in ordered lists (like 1.1, 1.2, 2.1, 2.2), we use CSS properties such as counter-reset, counter-increment, and the counters() function along with the display property to achieve proper formatting.

Nested List

A nested list or sub list is a list within a list. The key to correctly formatting nested lists in HTML is to recognize that the sub list is a child of a list item rather than a list itself.

Basic Nested List Example

Following is a simple nested ordered list without custom counters

<!DOCTYPE html>
<html>
<head>
   <title>Basic Nested List</title>
</head>
<body style="font-family: Arial, sans-serif; padding: 10px;">
   <h3>A Nested Ordered List</h3>
   <h4>Ice Creams</h4>
   <ol>
      <li>Chocolate
         <ol>
            <li>Chocolate Chips</li>
            <li>Belgian Dark Chocolate</li>
         </ol>
      </li>
      <li>Vanilla</li>
      <li>Strawberry</li>
   </ol>
</body>
</html>

The output shows default numbering without nested counters

A Nested Ordered List
Ice Creams
1. Chocolate
   1. Chocolate Chips
   2. Belgian Dark Chocolate
2. Vanilla
3. Strawberry

However, the above method does not create an ordered list with nested counters like 1.1, 1.2, 2.1, etc.

Syntax for Nested Counters

To create ordered lists with nested counters, we use the following CSS properties

counter-reset: counter-name;
counter-increment: counter-name;
content: counters(counter-name, "separator");
display: block | table;

Where counter-name is the name of the counter, separator is the character used to separate nested levels (usually "."), and display controls the layout behavior.

CSS Counter Properties for Nested Lists counter-reset Initializes counter at start of each parent element ol { counter-reset: item; } counter-increment Increases counter value by 1 for each list item li { counter-increment: item; } counters() Generates nested counter display (1.1, 1.2, 2.1) counters(item, ".")

Using Block Display for Nested Counters

An element with the display property set to block begins on a new line and occupies the full available width. By setting list items to display: block and using CSS counters, we can create nested numbering.

Example

Following example uses the block value of the display property for list items along with CSS counter properties

<!DOCTYPE html>
<html>
<head>
   <title>Nested Counters with Block Display</title>
   <style>
      .container {
         background-color: mistyrose;
         width: 300px;
         padding: 15px;
         border-radius: 5px;
         font-family: Arial, sans-serif;
      }
      ol {
         counter-reset: item;
         padding-left: 0;
      }
      li {
         display: block;
         color: purple;
         font-size: 16px;
         margin-bottom: 5px;
      }
      li:before {
         content: counters(item, ".") ". ";
         counter-increment: item;
         font-weight: bold;
      }
   </style>
</head>
<body style="padding: 10px;">
   <h3>Beverages</h3>
   <div class="container">
      <ol>
         <li>Coffee
            <ol>
               <li>Frappe</li>
               <li>Latte</li>
               <li>Cappuccino</li>
            </ol>
         </li>
         <li>Smoothie
            <ol>
               <li>Mango Smoothie</li>
               <li>Banana Smoothie</li>
            </ol>
         </li>
         <li>Mojito
            <ol>
               <li>Classic Mint Mojito</li>
               <li>Strawberry Mojito</li>
               <li>Blueberry Mojito</li>
            </ol>
         </li>
      </ol>
   </div>
</body>
</html>

The output displays nested counters in the format 1.1, 1.2, 2.1, etc.

Beverages
1. Coffee
   1.1. Frappe
   1.2. Latte
   1.3. Cappuccino
2. Smoothie
   2.1. Mango Smoothie
   2.2. Banana Smoothie
3. Mojito
   3.1. Classic Mint Mojito
   3.2. Strawberry Mojito
   3.3. Blueberry Mojito

Using Table Display for Nested Counters

Setting the display to table causes the element to behave like a table. The table-cell display value for the :before pseudo-element creates better alignment between the counter and the list content.

Example

Following example uses the table value for list items and table-cell for the counter display

<!DOCTYPE html>
<html>
<head>
   <title>Nested Counters with Table Display</title>
   <style>
      .container {
         background-color: rosybrown;
         color: beige;
         width: 280px;
         padding: 15px;
         border-radius: 5px;
         font-family: Arial, sans-serif;
      }
      ol {
         counter-reset: item;
         padding: 5px 0;
      }
      li {
         display: table;
         counter-increment: item;
         margin-top: 3px;
         width: 100%;
      }
      li:before {
         content: counters(item, ".") ". ";
         display: table-cell;
         padding-right: 10px;
         font-weight: bold;
         vertical-align: top;
      }
   </style>
</head>
<body style="padding: 10px;">
   <h3>Film Genres</h3>
   <div class="container">
      <ol>
         <li>Comedy
            <ol>
               <li>Romantic Comedy</li>
               <li>Action Comedy</li>
            </ol>
         </li>
         <li>Drama
            <ol>
               <li>Legal Drama</li>
               <li>Political Drama</li>
               <li>Medical Drama</li>
            </ol>
         </li>
         <li>Thriller
            <ol>
               <li>Psychological Thriller</li>
               <li>Crime Thriller</li>
            </ol>
         </li>
      </ol>
   </div>
</body>
</html>

The table display method provides better alignment between counters and content

Film Genres
1. Comedy
   1.1. Romantic Comedy
   1.2. Action Comedy
2. Drama
   2.1. Legal Drama
   2.2. Political Drama
   2.3. Medical Drama
3. Thriller
   3.1. Psychological Thriller
   3.2. Crime Thriller

Comparison of Display Methods

Following table compares the two display methods for nested counters

Display Block Method Display Table Method
Simpler CSS structure with fewer properties required. Better alignment between counters and content text.
List items stack vertically as block elements. Counter and text align as table cells side by side.
May have alignment issues with longer counter numbers. Maintains consistent spacing regardless of counter length.
Good for simple nested lists with short content. Ideal for complex nested lists with longer text content.

Key Points

  • counter-reset initializes the counter at the beginning of each ordered list (<ol>).

  • counter-increment increases the counter value by 1 for each list item.

  • counters() function generates the nested display format like "1.1", "1.2

Updated on: 2026-03-16T21:38:54+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements