使用 CSS 计数器

**CSS 计数器**允许您根据内容在文档中的位置调整内容的外观。例如,您可以使用计数器自动对网页上的标题进行编号,或更改有序列表的编号。

从本质上讲,计数器是由 CSS 维持的变量,其值可以通过跟踪使用次数的 CSS 规则来递增或递减。以下因素会影响元素上的计数器值

  1. 计数器从父元素继承或从之前的兄弟元素接收。
  2. 新的计数器使用counter-reset属性实例化。
  3. 计数器使用counter-increment属性递增。
  4. 计数器使用counter-set属性直接设置为某个值。

您可以定义您自己的命名计数器,也可以操作默认情况下为所有有序列表创建的list-item计数器。

使用计数器

要使用计数器,它必须首先使用counter-reset属性初始化为某个值。计数器的值可以使用counter-increment属性增加或减少,并可以使用counter-set属性直接设置为特定值。计数器的当前值使用counter()counters()函数显示,通常在伪元素content属性中。

计数器只能在生成盒子的元素中设置、重置或递增。例如,如果元素设置为display: none,则该元素上的任何计数器操作都将被忽略。

计数器的属性可以使用样式包含作用于特定元素,这在contain属性中更详细地描述。

操作计数器的值

要使用 CSS 计数器,它必须首先使用counter-reset属性初始化为某个值。该属性也可以用于将计数器值更改为任何特定数字。

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

css
counter-reset: section;

您还可以初始化多个计数器,可以选择为每个计数器指定一个初始值。下面我们将sectiontopic计数器初始化为默认值,并将page计数器初始化为 3。

css
counter-reset: section page 3 topic;

初始化后,可以使用counter-increment增加或减少计数器的值。例如,以下声明将在每个h3标签上将section计数器递增 1。

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

您可以在计数器名称后指定递增或递减量。它可以是正数或负数,但如果未提供整数,则默认为1

除了递增或递减之外,还可以使用counter-set属性将计数器显式设置为某个值。

css
.done::before {
  counter-set: section 20;
}

计数器名称不能为noneinheritinitial;否则声明将被忽略。

显示计数器

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

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

css
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 的普通计数器不同)。这使得实现从元素数量倒数到一的计数器变得容易。

例如,要创建一个名为 section 的反向计数器,并使用默认初始值,可以使用以下语法。

css
counter-reset: reversed(section);

当然,你可以指定任何你喜欢的初始值。

通过为 counter-increment 指定负值来减少计数器值。

注意: 你也可以使用 counter-increment 来递减非反向计数器。使用反向计数器的主要好处是默认初始值,以及 list-item 计数器会自动递减反向计数器。

计数器继承和传播

每个元素或伪元素在该元素的作用域内都有一组计数器。集合中的初始计数器从元素的父元素和前面的兄弟元素接收。计数器值从前一个兄弟元素的最后一个后代、最后一个兄弟元素或父元素接收。

当元素声明计数器时,计数器嵌套在从父元素接收的同名计数器中。如果父元素没有同名计数器,则将计数器按原样添加到元素的计数器集中。从前一个兄弟元素接收的同名计数器将从计数器集中删除。

counter() 函数检索提供的名称的最内层计数器。而 counters() 函数检索具有给定名称的整个计数器树。

在以下示例中,我们演示了一个名为 primary 的继承计数器和一个名为 secondary 的兄弟计数器。所有 <div> 元素都使用 counters() 函数显示其计数器。请注意,所有计数器都是使用 counter-reset 属性创建的,并且没有一个计数器被递增。

html
<section>
  counter-reset: primary 3
  <div>A</div>
  <div>B</div>
  <div>C</div>
  <div class="same-primary-name">D</div>
  <span> counter-reset: primary 6</span>
  <div>E</div>
  <div class="new-secondary-name">F</div>
  <span> counter-reset: secondary 5</span>
  <div>G</div>
  <div>H</div>
  <div class="same-secondary-name">I&nbsp;</div>
  <span> counter-reset: secondary 10</span>
  <div>J&nbsp;</div>
  <div>K</div>
  <section></section>
</section>
css
/* create 'primary' counter on divs' parent */
section {
  counter-reset: primary 3;
}

div::after {
  content: " ('primary' counters: " counters(primary, "-", style)
    ", 'secondary' counters: " counters(secondary, "-", style) ")";
  color: blue;
}

/* create new 'primary' counter */
.same-primary-name {
  counter-reset: primary 6;
}

/* create 'secondary' counter on div 'F' */
.new-secondary-name {
  counter-reset: secondary 5;
}

/* override the sibling 'secondary' counter */
.same-secondary-name {
  counter-reset: secondary 10;
}

section 元素用值为 3primary 计数器初始化,所有子 <div> 接收继承的 primary 计数器。元素“D”创建了一个新的 primary(值为 6)计数器,它嵌套在从父元素接收的计数器中,因此该元素有两个名为 primary 的计数器,值为 36

元素“F”首次创建 secondary(值为 5)计数器,并将该计数器传递给下一个兄弟元素“G”。元素“G”将计数器传递给下一个元素“H”,以此类推。接下来,元素“I”创建了一个同名 secondary(值为 10)的新计数器,但它丢弃了从前一个兄弟元素“H”接收的 secondary(值为 5)计数器,并将它自己的计数器传递给“J”。

counter-setcounter-reset 的区别

counter-set 属性更新现有计数器,如果不存在同名计数器,则实例化一个新计数器。counter-reset 属性始终创建新的计数器。

在以下示例中,我们有一个父列表中包含两个子列表。每个列表项都使用名为“item”的计数器编号。第一个子列表使用 counter-set 属性,第二个子列表使用 counter-reset 属性来更改“item”计数器。

html
<ul class="parent">
  <li>A</li>
  <li>B</li>
  <li>
    C (the counter updated using `counter-set`)
    <ul class="sub-list-one">
      <li>sub-A</li>
      <li>sub-B</li>
    </ul>
  </li>
  <li>D</li>
  <li>
    E (a new counter created using `counter-reset`)
    <ul class="sub-list-two">
      <li>sub-A</li>
      <li>sub-B</li>
      <li>sub-C</li>
    </ul>
  </li>
  <li>F</li>
  <li>G</li>
</ul>
css
/* create a new counter for the first time */
.parent {
  counter-reset: item 0;
}

/* increment the counter on each list item */
li {
  counter-increment: item;
}

/* show numbers on list items */
li::before {
  content: counter(item) " ";
}

/* change the existing counter value */
.sub-list-one {
  counter-set: item 10;
}

/* change the counter value */
.sub-list-two {
  counter-reset: item 0;
}

请注意第一个子列表项是如何从 11 开始接收编号的,并且编号在父列表中继续。这是因为 counter-set 属性更新了在 .parent 元素上声明的同一个“item”计数器。然后请注意第二个子列表项是如何从“1”开始接收新的编号的,并且它后面的父列表项没有继续编号。这是因为 counter-reset 属性创建了一个同名的新计数器,因此父列表项继续使用旧计数器。

列表项计数器

使用 <ol> 元素创建的有序列表隐式地包含一个名为 list-item 的计数器。

与其他计数器一样,它对向上计数器的默认初始值为 0,对反向计数器为“项目数量”。与作者创建的计数器不同,list-item 自动根据计数器是否反向,对每个列表元素递增或递减 1。

list-item 计数器可用于使用 CSS 操作有序列表的默认行为。例如,你可以更改默认初始值,或使用 counter-increment 来更改列表项递增或递减的方式。

示例

基本示例

此示例在每个标题的开头添加“Section [计数器的值]:”。

CSS

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

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

结果

基本示例:反向计数器

此示例与上面的示例相同,但使用的是反向计数器。如果你的浏览器支持 reversed() 函数符号,则结果将如下所示。

reversed counter

CSS

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

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

结果

更复杂的示例

计数器不必每次递增时都显示。此示例统计所有链接,只有在链接没有文本时才显示计数器,作为一种方便的替代方案。

CSS

css
:root {
  counter-reset: link;
}

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

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

HTML

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://mdn.org.cn/"></a></p>

结果

嵌套计数器示例

CSS 计数器对于制作带轮廓的列表特别有用,因为在子元素中会自动创建一个新的计数器实例。使用 counters() 函数,可以在不同级别的嵌套计数器之间插入分隔文本。

CSS

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

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>

结果

规范

规范
CSS 列表和计数器模块级别 3
# 自动编号

另请参阅