> ## Content Index
> Fetch the complete content index at: https://blog.hinablue.me/llms.txt
> Use this file to discover other available public pages before exploring further.

# [CSS 年終特賣] 讓 CSS 自動幫你數數
- URL: https://blog.hinablue.me/use-css-counter-to-make-your-own-toc/
- Published: 2011-12-30T03:35:00.000Z
- Updated: 2026-06-25T09:29:52.000Z
- Author: Hina Chen
- Tags: TOC, CSS

先來一下國語正音班。

> 數數，第一個字唸數，三聲數，第二個字唸數，四聲數。

最近因為在做 `TOC` 所以就把這個陳年的東西拿出來講一下，順便趁著*是芥末日*之前把一些筆記寫一寫，不然現在不寫，就只能明年才寫得完了（~~這個哏你要用幾次~~）。

我們在撰寫很長篇的文章的時候，常常需要主標題，副標題這一類的東西。但是最麻煩的地方在於，我如果中途一時興起多開了一個標題，那麼接下來的標題順序就悲劇了。

```
1. 我是第一章
  a. 我是第 1.1 章
2. 我是第二章
  a. 我是第 2.1 章
  b. 我是第 2.2 章
3. 我是第三章
  a. 我是第 3.1 章
  b. 我是第 3.2 章
  c. 我是第 3.3 章
  d. 我是第 3.4 章

```

如果我在 2, 3 章之中多開了一個章節，那麼，第三章勢必要跟著修改，這麼做的話不僅僅費時耗工，而且也很容易打錯（~~你累了嗎～~~）。

## 沒關係，CSS 已經為你想好了！

[12 Generated content, automatic numbering, and lists](http://www.w3.org/TR/CSS2/generate.html?ref=blog.hinablue.me)

> CSS 2.1 版本中，提供了 *Generated content, automatic numbering, and lists* 功能，而制定這些東西的年份冗長，最後一次修訂是在 2008 年 4 月。換句話說，這個東西已經存在超過 10 年之久。話雖如此，我們強大的**IE6/7/8 全部不支援**喔，~~啾咪~~

在 w3c 官方說明的 *12.4 Automatic counters and numbering* 提到，有兩種**數數**的設定方式。

- `counter-reset` 顧名思義，把計數器歸零（回到初始值，未必是零）
- `counter-increment` 顧名思義 part 2，把計數器**數數**

以上這兩種屬性只能用在元件與擬似元件（`pseudo-element`）上面，其他的地方用了是沒有反應的。另外，如果你的元件或是擬似元件沒有被產生或是被隱藏（`display: none`），那麼上面兩個屬性也是無效的。不過，倘若是看不見（`visibility: hidden`），這倒是會生效喔。

而且，有關於 `counter-reset` 在官方也有特別說明，在同一個元件上，如果要重設多個計數器，撰寫的方式是這樣的：

```
h1 {
    counter-reset: chapter section money nobody
}

```

重新設定計數器的寫法，可以組合 `計數器名稱` 與 `計數器初始值` 這兩種設定，也就是說，上述的重設範例，我還可以寫成這樣：

```
h1 {
    counter-reset: chapter 99 section -1 money 200000000 nobody
}

```

這樣的意思就是：

- `chapter` 這個計數器重設，初始值是 99
- `section` 這個計數器重設，初始值是 -1
- `money` 這個計數器重設，初始值是 ~~2 萬郝，1 夢想家~~ 200000000
- `nobody` 這個計數器重設，不給初始值所以固定是 0

這樣應該看得出重設屬性的精髓了吧，計數器可以隨時被重設，只要你高興的話要多少有多少。然而，我們有了初始值，就要開始累加（或是遞減）這個數字，這個時候就會用上**數數**器的屬性了。

```
h2 {
    counter-increment: chapter -2
    counter-increment: money 100
    counter-increment: nobody
}

```

這裡的 `counter-increment` 是依照你給的 `計數器` 與 `增量` 來計算這個數字是多少，以上面的例子，搭配我們當初所設定好的計數器，我們如果跑一次 `h2` 會得到下列的數值：

- `chapter` \= 97
- `money` \= 200000100
- `nobody` \= 1

這樣對於**數數**器應該就了解了吧。那，我們要怎麼把這些產生的數值，自動的幫我們放在標題的前面呢？這個時候就需要用到擬似元件（`pseudo-element`）這個東西了。什麼叫做擬似元件？

- `::before`
- `::after`

疑？不用懷疑，你可能很常看到這兩種 CSS 的選擇器。是的，他就是擬似元件。擬似元件中有一個屬性叫做 `content`，是專門用於產生擬似元件中的元素，但是，他只能是普通的字串。所以，我們就可以利用 `::before` 來產生我們所需要的東西。

~~不要問我為什麼不用 *::after*，如果你想把章節號放在章節名稱後面的話，你就用吧。~~

所以我們可以來看一個簡單的 TOC：

```
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>CSS Counter</title>
        <style>
            body {
                font: 16px/1.55 serif;
            }
            .toc {
                counter-reset: chapter;
            }
            .toc > ul > li {
                counter-increment: chapter;
                counter-reset: section;
                margin-left: 1em;
            }
            .toc > ul > li::before {
                content: counter(chapter);
                margin-right: 0.5em;
            }
            .toc > ul > li > ul > li {
                counter-increment: section;
                margin-left: 1em;
            }
            .toc > ul > li > ul > li::before {
                content: counter(chapter) "." counter(section);
                margin-right: 0.5em;
            }
        </style>
    </head>
    <body>

        <div class="toc">
            <ul>
                <li>這是第x章，啦啦啦啦
                    <ul>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                    </ul>
                </li>
                <li>這是第x章，啦啦啦啦
                    <ul>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                    </ul>
                </li>
                <li>這是第x章，啦啦啦啦
                    <ul>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                    </ul>
                </li>
                <li>這是第x章，啦啦啦啦
                    <ul>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                    </ul>
                </li>
                <li>這是第x章，啦啦啦啦
                    <ul>
                        <li>這是第x節，啦啦啦啦啦啦</li>
                    </ul>
                </li>
            </ul>
        </div>
    </body>
</html>

```

如果想看範例結果，可以[連去這裡看看](http://jsfiddle.net/hinablue/5Dd48/?ref=blog.hinablue.me)，記得 IE6/7/8 全部都不支援喔，~~啾咪~~

TOC 還有一個隱憂，就是頁碼計算。不過，由於我沒說 CSS 可以拿來寫書，所以頁碼還是交給專門的文件產出軟體吧。這個計數器功能，讓你在冗長文件目錄下，製作錨點時特別有幫助。畢竟，記得閱讀到什麼章節，數字或是代碼永遠比章節名稱要好記得多啊。