首页 > 解决方案 > 当使用 CSS 计数器自动编号标题时,应该在哪里使用 counter-reset?

问题描述

我想使用 CSS 自动对 HTML 文档中具有多个层次结构的标题进行编号。我在 Internet 上找到的示例广泛使用了 counter-reset,但我怀疑这通常是对 counter-reset 的错误使用,因为它在我测试过的任何配置下都不适用于我。

h3 计数器(小节)应在每个新的 h2 处重置。

考虑以下简单的代码示例:

body {
  counter-reset: section subsection;
}

.countheads>h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
  counter-reset: subsection;
}

.countheads>h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>


  </div>
</body>

预期的行为是第 II 部分中的小节再次从 1 开始,如 II.1、II.2 中。

如果我将 counter-reset 语句更改为 counter-set,我会得到想要的结果:

body {
  counter-reset: section subsection;
}

.countheads > h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
  counter-set: subsection;
}

.countheads > h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3> 
      Third point
    </h3>


  </div>
</body>

使用一些语法荧光笔,counter-set 语句被标记为红色,暗示一个错误,但它却做了我想要的。但是为什么在这种情况下计数器重置不起作用呢?

标签: htmlcsscss-counter

解决方案


您需要在内部重置h2并且没有伪元素:

body {
  counter-reset: section subsection;
}

.countheads > h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
}

/* .countheads > h2 + h3: use this selector in case you have an issue with Firefox */
.countheads > h2 {
  counter-reset: subsection;
}

.countheads > h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>


  </div>
</body>

counter-set也会这样做,因为

每次出现元素时将计数器设置为的值。如果未指定,则默认为 0。如果元素上当前没有给定名称的计数器,则元素将创建一个给定名称的新计数器,起始值为 0 ref

在您的情况下,计数器已经存在,因此不会被创建。


规范

counter-reset属性实例化元素上的新计数器并将它们设置为指定的整数值。

counter-incrementcounter-set属性操纵现有计数器的值。如果元素上还没有给定名称的计数器,它们只会实例化新的计数器。

还有更重要的

因此,计数器的范围从文档中实例化该计数器的第一个元素开始,并包括该元素的后代及其后续兄弟姐妹及其后代。

因此,如果您使用counter-reset,您将创建一个范围仅限于伪元素的实例,但使用counter-set将简单地修改具有不同范围的上层已经实例化的计数器。

用编程语言做一个类比

int i = 0;
function a() {
   i = 0; /* this is counter-set */
}
function b() {
   int i = 0; /* this is counter-reset */
}

推荐阅读