How to use CSS counters to beautify ordered lists of numbers

How to use CSS counters to beautify ordered lists of numbers

In web design, it is very important to use an organized method to display data so that users can clearly understand the data structure and content displayed on the website. Using an ordered list is a simple way to achieve an organized display of data.

If you need more in-depth control over the styling of the ordered list numbers, you might find that you have to add more html DOM structure or do it through JavaScript . Fortunately, this problem can be solved much more easily using CSS計數器.

In this tutorial, we will learn what CSS計數器are and some use cases.

The problem with ordered lists

When you write an ordered list like the following, the browser will automatically add numbers in front of the list items.

<ol>
  <li>My First Item</li>
  <li>My Second Item</li>
  <li>My Third Item</li>
</ol> 

This looks fine, but it doesn't allow you to style the numbers. Suppose, you need to modify the list by putting the numbers in front of it in a circle, what would you do?

One way is to remove the list entirely, and manually add the numbers yourself.

<div>
  <span>1</span> My First Item
</div>
<div>
  <span>2</span> My Second Item
</div>
<div>
  <span>3</span> My Third Item
</div>
div {
  margin-bottom:10px;
}
div span {
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:25px;
  height:25px;
  border-radius:50%;
  background-color:#000;
  color:#fff;
} 

This is exactly what we want to achieve, but it also has some drawbacks. First, adding numbers manually is cumbersome. If you need to change a number, you have to change them one by one. In this case, you can use JavaScript to dynamically add <span> tags to solve these problems, but this will add more nodes to DOM , resulting in a large amount of memory usage.

In most cases, it is better to use CSS counters. Let’s look at why.

Introduction to CSS Counters

CSS計數器are page-scope variables whose values ​​can be changed using CSS rules.

First, set the counter using the counter-reset property. list-number is the variable name used here.

div.list {
  counter-reset: list-number;
}

Next, use counter-increment property to increase the value of the counter.

div.list div {
  counter-increment: list-number;
}

Now, every time a div.listdiv element appears, list-number variable will increase by one.

Finally, we use the :before pseudo-element with a set content property and counter() function to display the number.

div.list div:before {
  content: counter(list-number);
}

Here is the full code:

<div class="list">
  <div>My first item</div>
  <div>My second item</div>
  <div>My third item</div>
</div>
div.list {
  counter-reset: list-number;
}
/** You can use counter-increment in :before elements **/
div.list div:before {
  counter-increment: list-number;
  content: counter(list-number);
}

Now we are not quite there yet. Let's style the :before pseudo-element to make it look better.

div.list div:before {
  counter-increment: list-number;
  content: counter(list-number);
  
  margin-right: 10px;
  margin-bottom:10px;
  width:35px;
  height:35px;
  display:inline-flex;
  align-items:center;
  justify-content: center;
  font-size:16px;
  background-color:#d7385e;
  border-radius:50%;
  color:#fff;
}

Modify the starting number

By default, counter-reset sets the counter to 0. When the first counter-increment is called it starts at 1. You can set the initial value by passing an integer as the second argument to counter-reset function.

div.list {
  counter-reset: list-number 1;
} 

If you want to start from 0 , you can set the initial value to -1 .

div.list {
  counter-reset: list-number -1;
} 

Change the increment value

By default, counter-increment increases the value of the counter by one. Just like counter-reset , you can define an offset value for counter-increment property.

In this example, counter-reset sets list-number to 0 . Each time counter-increment is called, list-number number increases by 2 , so you will see the list numbers 2 , 4 , and 6 .

div.list {
  counter-reset: list-number;
}
div.list div:before {
  counter-increment: list-number 2;
  // other styles
} 

Counter format

counter() function can take two parameters: counter-name and counter-format . For the second argument, you can use any valid list type value, including:

  • decimal (eg, 1, 2, 3…)
  • lower-latin (eg, a, b, c…)
  • lower-roman (eg, i, ii, iii…)

The default value is a number.

For example, if you're scientific like me, you could use lower-greek letters for the numbered values.

div.list div:before {
  counter-increment: list-number;
  content: counter(list-number, lower-greek);
  // ... other styles
} 

Nested counters

When using nested order lists, numbers are always displayed in this format:

If you need numeric numbers for sublist items (for example, 1.1), you can use CSS計數器with counters() function.

<ol>
  <li>
     My First Item
    <ol>
      <li>My Nested First Item</li>
      <li>My Nested Second Item</li>
    </ol>
  </li>
  <li>My Second Item</li>
</ol>
ol {
  list-style-type:none;
  counter-reset:list;
}
ol li:before {
    counter-increment:list;
    content: counters(list, ".") ". ";
}

Note that we are using the counters() function instead of counter() function.

The second parameter of counters() function is the connection string. It can also have a third argument to set the format (for example, Greek or Roman numerals).

Nested counter with title

Elements like <h1> , <h2> are not nested in the document. They appear as different elements but still represent a hierarchy. Here's how to set nested numbers into your title:

body {
  counter-reset:h1;
}
h1 {
  counter-reset:h2;
}
h1:before {
  counter-increment: h1;
  content: counter(h1) ". ";
}
h2:before {
  counter-increment:h2;
  content: counter(h1) "." counter(h2) ". ";
}

Each time <h1> is found, the <h2> counter is reset. <h2> is given a number in the document relative to <h1> .

Browser support

Thankfully, CSS counters have gained widespread browser support since their introduction with CSS2 . Although using the counter() function with properties other than content is still experimental, you can execute all the examples covered in this tutorial without hesitation.

A simple challenge

Are you ready for a simple challenge involving CSS counters?

Use CSS計數器to display 1 to 1000 with their Roman characters in just 10 lines of code.

If you’re stumped, here’s how you can do it:

To create 1000 div elements you could use the following.

for (var i = 0; i < 1000; i++) {
  document.body.appendChild( document.createElement("div") );  
}

CSS Counters:

body {
  counter-reset:number;
}
div:before {
  counter-increment:number;
  content: counter(number) " => " counter(number, lower-roman);
}

in conclusion

CSS counters are a little-known feature in CSS, but you'd be surprised how often they come in handy. In this tutorial, we discussed how and when to use CSS counters and showed some examples.

Following is the list of properties we use.

property usage
counter-reset Reset (or create) a given value counter (default 0)
counter-increment Increment the given counter by the given offset (default 1)
counter(counter-name, counter-format) Get the value of the counter in the given format
counters(counter-name, counter-string, counter-format) Get the value of a nested counter in a given format

CSS counters are cool though. But one thing to understand is that all counters are global. If you are working in a large project with many CSS files, you may not be able to find where they are created, reset and incremented. Don't overuse them, and be sure to use descriptive names for counters to avoid conflicts.

Some practical examples

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Counter</title>
  <style>
    html {
      box-sizing: border-box;
      font-size: 62.5%;
    }

    *,
    *::before,
    *:after {
      box-sizing: inherit;
    }

    body {
      font-family: Rambla, sans-serif;
      font-size: 2rem;
      line-height: 1.5;
      color: #03c03c;
    }

    h1 {
      text-align: center;
    }

    .wrapper {
      margin: 0 auto;
      width: 85%;
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-justify-content: space-around;
      -ms-flex-pack: distribute;
      justify-content: space-around;
    }

    @media (max-width: 1100px) {
      .wrapper {
        -webkit-box-orient: vertical;
        -webkit-box-direction: normal;
        -webkit-flex-direction: column;
        -ms-flex-direction: column;
        flex-direction: column;
        -webkit-box-align: center;
        -webkit-align-items: center;
        -ms-flex-align: center;
        align-items: center;
      }
    }

    ol {
      counter-reset: li;
      margin: 20px 0;
      padding-left: 0;
    }

    ol>li {
      position: relative;
      margin: 0 0 25px 2em;
      padding: 4px 8px 4px 20px;
      list-style: none;
    }

    ol>li::before {
      content: counter(li);
      counter-increment: li;
      position: absolute;
      top: -2px;
      left: -2em;
      width: 2em;
      margin-right: 8px;
      padding: 4px;
      font-weight: bold;
      text-align: center;
    }

    li ol,
    li ul {
      margin-top: 6px;
    }

    ol ol li:last-child {
      margin-bottom: 0;
    }

    .disc>li::before {
      color: white;
      background-color: #03c03c;
      border-radius: 50%;
    }

    .circle>li::before {
      color: #03c03c;
      border: solid 2px #03c03c;
      border-radius: 50%;
    }

    .angle>li::before {
      color: #03c03c;
      border-right: solid 3px #03c03c;
      border-bottom: solid 3px #03c03c;
    }

    .shadow>li::before {
      color: white;
      background: #03c03c;
      box-shadow: 5px 5px 0 0 greenyellow;
    }

    .rombo>li {
      margin-bottom: 25px;
    }

    .rombo>li::before {
      color: white;
      z-index: 2;
    }

    .rombo>li::after {
      position: absolute;
      top: -2px;
      left: -2em;
      width: 2em;
      margin-right: 8px;
      padding: 4px;
      background-color: #03c03c;
      height: 2em;
      -webkit-transform: rotate(45deg);
      -ms-transform:rotate(45deg);
      transform: rotate(45deg);
      content: '';
      z-index: 1;
    }

    .underline>li::before {
      border-bottom: solid 3px #03c03c;
    }
  </style>
</head>

<body>
  <h1>Styling Ordered List Numbers</h1>
  <div class="wrapper">
    <ol class="disc">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
    <ol class="circle">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
    <ol class="angle">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
    <ol class="shadow">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
    <ol class="rombo">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
    <ol class="underline">
      <li>Tomato</li>
      Cucumber
      <li>Onion</li>
      <li>Pepper</li>
    </ol>
  </div>
  More examples
</body>
</html>

More excellent cases

https://css-tricks.com/custom-list-number-styling/

This concludes this article on how to use CSS counters to beautify ordered lists of numbers. For more information about CSS counters of ordered lists of numbers, please search previous articles on 123WORDPRESS.COM or continue browsing the related articles below. I hope you will support 123WORDPRESS.COM in the future!

This concludes this article on how to use CSS counters to beautify ordered lists of numbers. For more information about CSS counters of ordered lists of numbers, please search previous articles on 123WORDPRESS.COM or continue browsing the related articles below. I hope you will support 123WORDPRESS.COM in the future!

<<:  SQL optimization often makes mistakes, that's because you don't understand the usage of MySQL explain plan

>>:  Introduction to common commands and shortcut keys in Linux

Recommend

How to change the domestic image source for Docker

Configure the accelerator for the Docker daemon S...

CentOS7 upgrade kernel kernel5.0 version

Upgrade process: Original system: CentOS7.3 [root...

Docker builds cluster MongoDB implementation steps

Preface Due to the needs of the company's bus...

The use of setState in React and the use of synchronous and asynchronous

In react, if you modify the state directly using ...

How to view and clean up Docker container logs (tested and effective)

1. Problem The docker container logs caused the h...

Detailed analysis of when tomcat writes back the response datagram

The question arises This question arose when I wa...

Vue implements the drag and drop sorting function of the page div box

vue implements the drag and drop sorting function...

How to create users and manage permissions in MySQL

1. How to create a user and password 1. Enter the...

MySQL Index Optimization Explained

In daily work, we sometimes run slow queries to r...

Solve the problem of ifconfig being unavailable in docker

Recently, when I was learning docker, I found tha...

About the problem of dynamic splicing src image address of img in Vue

Let's take a look at the dynamic splicing of ...

Sqoop export map100% reduce0% stuck in various reasons and solutions

I call this kind of bug a typical "Hamlet&qu...

Vue implements DingTalk's attendance calendar

This article shares the specific code of Vue to i...