使用 CSS 计数器

CSS 计数器可让你根据内容在文档中的位置调整其显示的外观。例如,你可以使用计数器自动为网页中的标题编号,或者更改有序列表的编号。

本质上 CSS 计数器是由 CSS 维护的变量,这些变量可能根据 CSS 规则跟踪使用次数以递增或递减。你可以自定义一个计数器,也可以修改 list-item 这一默认生成的应用于所有有序列表的计数器。

使用计数器

在使用计数器之前,必须使用 counter-reset 属性初始化计数器的值。计数器可通过 counter-increment 属性指定其值为递增或递减。当前计数器的值可通过 counter()counters() 函数显示出来,这通常会在伪元素content 属性中使用。

请注意,计数器只能在可以生成盒子的元素中使用(设置或重设值、递增)。例如,如果一个元素被设置为了 display: none,那么在这个元素上的任何计数器操作都会被忽略。

操作计数器的值

在使用计数器之前,需要使用 counter-reset 属性来初始化它的值。这个属性也可用于指定计数器的初始值。

下面,我们将名为 section 的计数器初始化为默认值(0)。

counter-reset: section;

你也可以同时初始化多个计数器,并可以指定其初始值。下面,我们将名为 sectiontopic 的计数器初始化为默认值,并将 page 计数器的初始值指定为 3。

counter-reset: section page 3 topic;

在初始化之后,计数器的值就可以使用 counter-increment 来指定其为递增或递减。例如,下面声明了一个随着 h3 标签递增的 section 计数器。

h3::before {
  counter-increment: section; /* Increment the value of section counter by 1 */
}

你可以在计数器的名称后指定单次递增或递减的值(正数或负数)。

计数器的名称不可以为 noneinheritinitial,否则,相应的声明会被忽略。

显示计数器

计数器的值可以使用 counter()counters() 函数以在 content 属性中显示。

例如,以下使用 counter() 声明的计数器会在每一个 h3 标题前面添加文本 Section <number>:,其中的 <number> 是十进制计数的值(默认显示样式):

h3::before {
  counter-increment: section;                 /* Increment the value of section counter by 1 */
  content: "Section " counter(section) ": ";  /* Display counter value in default style (decimal) */
}

当不需要包含父级上下文的编号,而仅需要嵌套内容的编号时,应使用 counter() 函数。例如,以下示例的每一个嵌套内容的计数都从 1 开始:

1 One
  1 Nested one
  2 Nested two
2 Two
  1 Nested one
  2 Nested two
  3 Nested three
3 Three

当需要同时包含父级上下文和嵌套内容的编号时,应使用 counters() 函数。例如,以下示例的每一个嵌套内容会包含父级编号:

1 One
  1.1 Nested one
  1.2 Nested two
2 Two
  2.1 Nested one
  2.2 Nested two
  2.3 Nested three
3 Three

counter() 函数有两种形式: counter(<counter-name>)counter(<counter-name>, <counter-style>)。生成的文本是伪元素范围内指定名称的最内层计数器的值。

counters() 函数也同样有两种形式:counters(<counter-name>, <separator>)counters(<counter-name>, <separator>, <counter-style>)。生成的文本由在伪元素范围内所有指定名称的计数器的值组成。这些值从最外层到最内层,使用指定的字符串(<separator>)分隔。

以上两个函数均可以使用指定的 <counter-style> 来渲染其值(默认值为 decimal)。你也可以使用 list-style-type 属性其它可选的值,或自定义样式

基础示例计数器嵌套示例这两个示例分别展示了 counter()counters() 的使用方法。

反向计数器

反向计数器是一种用于递减(而非递增)的计数器。反向计数器可以通过在 counter-reset 属性中将计数器的名称使用 reversed() 函数包裹来创建。

反向计数器的默认初始值与元素的数量相同(不同于常规的默认初始值为 0 的计数器)。这使得实现从元素数量为初始值倒数到 1 的计数器变得更加容易。

例如,要创建一个名为 section 反向计数器(使用默认初始值),你只需要这样写:

counter-reset: reversed(section);

你也可以指定它的初始值。

计数器的值会随着通过 counter-increment 属性指定的负数递减。

备注: 对于非反向计数器,你也仍然可以使用 counter-increment 属性实现递减。使用反向计数器的优点在于:其默认初始值可以自动根据元素数量生成,自动应用于有序列表的 list-item 计数器也可以借此反转编号。

有序列表(list item)计数器

使用 <ol> 元素创建的有序列表,会自动应用名为 list-item 的计数器。

和其它的计数器一样,其也是一个默认自增(+1)且初始值为 0 的计数器,对于反向计数器,则以元素数量为初始值,且默认自减(-1)。与自定义的计数器不同,list-item 是根据其是否为反向计数器而自动自增或自减的。

可以通过 CSS 修改 list-item 计数器应用在有序列表上的默认行为。例如,你可以改变默认初始值,或使用 counter-increment 改变递增或递减的方式。

示例

基础示例

以下示例会在每一个标题前添加一个“Section [the value of the counter]:”字符串。

CSS

body {
  counter-reset: section;                      /* Set a counter named 'section', and its initial value is 0. */
}

h3::before {
  counter-increment: section;                  /* Increment the value of section counter by 1 */
  content: "Section " counter(section) ": ";   /* Display the word 'Section ', the value of
                                                  section counter, and a colon before the content
                                                  of each h3 */
}

HTML

<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>

结果

基础示例:反向计数器

以下示例与上一个类似,区别在于其使用了反向计数器。如果你的浏览器支持 reversed() 函数,其结果就会类似于这样:

reversed counter

CSS

body {
  counter-reset: reversed(section);           /* Set a counter named 'section', and its initial value is 0. */
}

h3::before {
  counter-increment: section -1;              /* Decrement the value of section counter by 1 */
  content: "Section " counter(section) ": ";  /* Display the word 'Section ', the value of
                                                 section counter, and a colon before the content
                                                 of each h3 */
}

HTML

<h3>Introduction</h3>
<h3>Body</h3>
<h3>Conclusion</h3>

结果

一个更加复杂的示例

有时我们不需要让计数器在每一次递增时都显示其值,以下示例仅在链接的内容为空时将其替换为由计数器生成的值。

:root {
  counter-reset: link;
}

a[href] {
  counter-increment: link;
}

a[href]:empty::after {
  content: "[" counter(link) "]";
}

HTML

<p>See <a href="https://www.mozilla.org/"></a></p>
<p>Do not forget to <a href="contact-me.html">leave a message</a>!</p>
<p>See also <a href="https://developer.mozilla.org/"></a></p>

结果

计数器嵌套示例

CSS 计数器对创建目录(多级有序列表)特别有用,因为其会在子元素中自动创建一个 CSS 计数器的实例。使用 counters() 函数,可以在不同级别的嵌套计数器之间可以插入分隔字符串。

CSS

ol {
  counter-reset: section;                /* Creates a new instance of the
                                            section counter with each ol
                                            element */
  list-style-type: none;
}

li::before {
  counter-increment: section;            /* Increments only this instance
                                            of the section counter */
  content: counters(section, ".") " ";   /* Combines the values of all instances
                                            of the section counter, separated
                                            by a period */
}

HTML

<ol>
  <li>item</li>          <!-- 1     -->
  <li>item               <!-- 2     -->
    <ol>
      <li>item</li>      <!-- 2.1   -->
      <li>item</li>      <!-- 2.2   -->
      <li>item           <!-- 2.3   -->
        <ol>
          <li>item</li>  <!-- 2.3.1 -->
          <li>item</li>  <!-- 2.3.2 -->
        </ol>
        <ol>
          <li>item</li>  <!-- 2.3.1 -->
          <li>item</li>  <!-- 2.3.2 -->
          <li>item</li>  <!-- 2.3.3 -->
        </ol>
      </li>
      <li>item</li>      <!-- 2.4   -->
    </ol>
  </li>
  <li>item</li>          <!-- 3     -->
  <li>item</li>          <!-- 4     -->
</ol>
<ol>
  <li>item</li>          <!-- 1     -->
  <li>item</li>          <!-- 2     -->
</ol>

结果

规范

Specification
CSS Lists and Counters Module Level 3
# auto-numbering

参见