Press enter to go to start of page

Cascading Stylesheets

Counters

Learning Outcomes

On completion of this lesson you will learn:

Go to top

Introduction

HTML provides us with a means of numbering lists of items by using the <ol></ol> element. The problem with this is that one cannot separate the numbers from the lines that they number.

If we wish to format the numbers separately we must use the CSS counter.

Go to top

A basic Counter Example

For our first example we shall start with a list of paragraphs that we want numbered. The HTML file is shown below.

Listing 1
                        <!doctype html>
                        <html lang="en">
                            <head>
                                <link href="Counters.css" rel="stylesheet" type="text/css">
                                <meta charset="utf-8">
                            </head>
                            <body>
                                <h3>House Rules</h3>
                                <p>Residents must leave building by 9:00 AM</p>
                                <p>Residents must return to building before 8:00 PM</p>
                                <p>No alcohol allowed in any part of the building</p>
                                <p>Lights out by 10:00 PM</p>   
                            </body>
                        </html>
                    

The code here is simple enough that there is no need to explain it. Without any styling it would render on a web page as in Fig 1 below.

A list of paragraphs without numbers
Fig 1: Raw text

Cross-referencing Fig 1 with Listing 1 we see that the four rules the residents must follow comprise of a paragraph each. Our aim is to style the paragraphs with a number that uniquely identifies each paragraph.

Listing 2 below show the CSS code for numbering the paragraphs.

Listing 2
                        body{
                            counter-reset: ruleCounter
                        }
                        p::before{
                            counter-increment:  ruleCounter;
                            content: counter(ruleCounter) ": ";
                        }
                    

At line 2 the counter-reset property creates a counter named ruleCounter and initialises it to zero. This starts off the counting process. If you are familiar with programming this is equivalent to creating and initialising a global variable.

Lines 4 to 7 is somewhat more complex. We shall begin with line 4. p and before are separated by a double colon. This means that before is a pseudo-elelennt that is attached to p.

As an element it can be styled like any other element you are familiar with. This rule is activated whenever the browser encounters a paragraph element.

Once rule is activated, two events occur:

When the second paragraph is encountered, the same sequence of events occur, except that now the value of ruleCounter Will be 2. Smilarly its value will be incremented to 3 and 4 respectively.

A list of numbered paragraphs
Fig 2: Paragraphs numbered using counter
Go to top

Using two Counters

In the example we have just completed we had a single <h3> heading followed by a list of paragraphs. In this case there was no rason for us to have more than one counter since we we had only one heading: 'House Rules'

Looking at Listing 3 below we have two level 3 headings at lines 8 and 13. If we have two Level 3 headings there is no reason why we should not have more headings at the same level. Therefore it is time that we put counters on the headings as well.

One other thing we have to be aware of is the numbering of the paragraphs. The paragraphs belonging to 'House Rules' which spans lines 9 to 12, would be numbered from 1 to 4 and the paragraphs belonging to 'Reasons for Eviction' should be numbered from 1 to 3.

Simply put, we need to reset the paragraph counter half way through the operation.

Listing 3
                        <!doctype html>
                        <html lang="en">
                            <head>
                                <link href="Counters.css" rel="stylesheet" type="text/css">
                                <meta charset="utf-8">
                            </head>
                            <body>
                                <h3>House Rules</h3>
                                <p>Residents must leave building by 9:00 AM</p>
                                <p>Residents must return to building before 8:00 PM</p>
                                <p>No alcohol allowed in any part of the building</p>
                                <p>Lights out by 10:00 PM</p>
                                <h3>Reasons for Eviction</h3>
                                <p>Alcohol in room</p>
                                <p>Allowing in strangers</p>
                                <p>Lights on after 10:00 PM</p>
                            </body>
                        </html>
                    

In order to be able to count the <h3> and the <p> levels we need two counters. In the previous example we had a counter for the <p> elements named ruleCounter and so we will carry this counter with us into the current version.

We also need to count the <h3> occurrences. For this we shall use a counter named h3Counter.

Looking at Listing 3 we see that h3 is the top level group and that p is a subgroup of it. This means that the paragraphs in lines 9 to 12 will be numbered numerically starting at 1. The paragraphs at lines 14 to 16 should be numbered also starting at 1 since they belong to a different group. This means that the counter ruleCounter needs to be reset back to zero at this point.

Listing 4 below shows us how this is done.

Listing 4
                        body{
                            counter-reset:  h3Counter ;
                        }
                        h3{
                            counter-reset: ruleCounter;
                        }
                        h3::before{
                            counter-increment: h3Counter;
                            content: counter(h3Counter) " ";
                        }
                        p::before{
                            counter-increment:  ruleCounter;
                            content: counter(ruleCounter) ": " ;
                        }
                    

At line 2 h3Counter is initialised to zero. This is done at body level since this counter does not need to be reset.

At line 5 the variable ruleCounter is reset to zero. This occurs at h3 level. Since the h3 tag occurs at lines 8 and 13, ruldCounter will be reset to zerro at those two points, The result of this is that lines 9 and 14 will will start counting at 1.

A list of numbered paragraphs using two counting levels
Fig 3: Paragraphs grouped on two levels

Here we see that the h3 groups are numbered from from 1 to 2 at the top level, while the paragraphs are numbered starting at 1 within each group.

Go to top

Styling the counters

We shall conclude this lesson with a few suggestions for styling or list. The great advantage of using counters instead of the <ol> is that you can style the line numbers and the text separately. This is because the line numbers are stored in the ::before pseudo-element. It has both width and height properties and therefore lends itself to a wide range of styling possibilities.

Below is the modified CSS file which now contains styling code.

Listing 5
                        body{
                            counter-reset:  h3Counter ;
                            background-color: orange;
                            font-weight: bold;
                            color: #008
                        }
                        h3{
                            counter-reset: ruleCounter;
                        }
                        h3::before{
                            counter-increment: h3Counter;
                            content: counter(h3Counter) " ";
                            margin-right: 10px;
                            margin-bottom:10px;
                            width:45px;
                            height:45px;
                            display:inline-flex;
                            align-items:center;
                            justify-content: center;
                            font-size:1.5rem;
                            font-weight: bold;
                            background-color:#008;
                            border-radius:50%;
                            color:beige;
                            border: medium solid black;
                        }
                        p::before{
                            counter-increment:  ruleCounter;
                            content: counter(ruleCounter);
                            margin-right: 10px;
                            margin-bottom:10px;
                            width:35px;
                            height:35px;
                            display:inline-flex;
                            align-items:center;
                            justify-content: center;
                            font-size:1rem;
                            font-weight: bold;
                            background-color:beige;
                            border-radius:50%;
                            color:#008;
                            border: medium solid #008;
                        }
                    

We shall not discuss the modified CSS file above as the extra code we added is purely decorative and therefore should be familiar to you by now.

A styled list
Fig 3: Nested lists with each level styled differently

The above image show what the two level list looks like after being styled according to Listing 5.

Go to top

Summary

The uploaded file is an educational HTML document titled "CSS | Counters," focused on the concept of CSS counters for styling lists and elements. It begins with a navigation header linking to related topics like box models, inheritance, selectors, and responsive design. The primary section introduces counters, explaining their use for formatting numbers separately from text in HTML using the <ol> element and the CSS `counter` property.

The document progresses to provide a basic example where paragraphs are numbered using a counter named `ruleCounter`. It explains the implementation through the `counter-reset`, `counter-increment`, and `content` properties, detailing how the pseudo-element `::before` is styled to add numbers dynamically to paragraphs. The example highlights the process of initializing, incrementing, and displaying the counter values alongside paragraph content.

Building on this, the file describes how to use multiple counters to handle nested lists. It introduces a second counter, `h3Counter`, to number <h3> headings while resetting the paragraph counter (`ruleCounter`) within each heading group. This demonstrates hierarchical numbering, where top-level elements and their subgroups maintain distinct numbering schemes.

The final section explores styling counters, showcasing how CSS can be used to customize the appearance of numbered lists. Examples include adding spacing, adjusting font sizes, and applying decorative elements like colored backgrounds, borders, and rounded corners to the `::before` pseudo-element. The document concludes with visual examples and references to external resources, such as MDN, blogs, and tutorials, for further learning on CSS counters.

Go to top

Revision

Multi choice

Fill in the blanks

Go to top

Assignment

1. Basic Concept: Begin by explaining the primary purpose of CSS counters. Include a description of the difference between HTML's <ol> element for numbered lists and the flexibility offered by CSS counters. Use the provided examples to illustrate your points.

2. Implementation: Delve into the mechanics of implementing a basic CSS counter. Describe the role of `counter-reset`, `counter-increment`, and the `::before` pseudo-element. Use examples from the lesson, such as the "House Rules" example, to explain how these properties work together to add dynamic numbering to paragraphs.

3. Nested Counters: Discuss the concept of using multiple counters within the same document. Explain the need for hierarchical numbering, as seen in the example with headings (`h3Counter`) and their associated paragraphs (`ruleCounter`). Highlight how `counter-reset` is strategically applied to achieve this nested structure.

4. Styling Counters: Explain the advantage of using CSS counters for styling purposes. Describe how the `::before` pseudo-element can be styled independently of the content it precedes. Include examples of styling choices, such as adjusting font size, background color, borders, and alignment, to create visually appealing numbered lists.

5. Summary: Conclude by summarizing the benefits of using CSS counters over traditional HTML <ol> tags. Discuss how counters enhance flexibility and design possibilities in web development.

Your submission should demonstrate a clear and thorough understanding of the CSS counter properties and their practical applications. Ensure your narrative is detailed, cohesive, and supported by the examples provided in the lesson. Use technical terminology appropriately and make connections between concepts to illustrate your mastery of the topic.

Go to top