11

在下面的代码中,我需要使用divHTML 顶部的标签进行样式设置。如果没有div标签,hx标签的轮廓编号是正确的,但如果标签到位,div一切都会完全出错。我需要这样工作,但div标签仍然存在,我需要它为具有不同 id 的 div 工作。有任何想法吗?

body {counter-reset: h1}
h1 {counter-reset: h2}
h2 {counter-reset: h3}

h1:before {counter-increment: h1; content: counter(h1) ". "}
h2:before {counter-increment: h2; content: counter(h1) "." counter(h2) ". "}
h3:before {counter-increment: h3; content: counter(h1) "." counter(h2) "." counter(h3) ". "}
<div class="varies">
    <h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h1>
</div>
<p>Morbi efficitur nibh metus, a vehicula mauris tristique ac. Duis ornare metus eget iaculis hendrerit.</p>
  <h2>Morbi nisi lacus, ultricies sit amet turpis a, aliquet congue nulla.</h2>
        <p>Duis eget facilisis nisl.</p>
    <h3>Donec tincidunt purus quam, ut accumsan lorem hendrerit a.</h3>
      <p>Aenean in mattis quam.</p>
    <h3>Maecenas a nulla sit amet ligula facilisis tincidunt lacinia non enim.</h3>
      <p>Aliquam dignissim turpis placerat, facilisis magna et, venenatis purus.</p>
  <h2>Suspendisse tempus eu elit nec malesuada.</h2>
        <p>In ut sollicitudin nisi. Praesent non porttitor ante, molestie scelerisque mauris.</p>
  <h2>Vivamus eu turpis efficitur, ornare risus in, consectetur tellus.</h2>
        <p>Cras pellentesque orci eu placerat mollis.</p>      
<h1>Duis eu nulla et tellus porttitor auctor.</h1>

4

2 回答 2

10

可以通过查看W3C 规范关于计数器的创建、它们的范围和继承的内容来详细解释这种行为的原因。

计数器重置: counter-reset 属性在元素上创建新的计数器。

计数器的范围:计数器的范围从文档中具有该计数器的“计数器重置”的第一个元素开始。

计数器继承:计数器及其值是分开继承的,可能来自不同的元素。如果一个元素有一个先前的兄弟,它必须继承所有兄弟的计数器。否则,如果元素有父元素,它必须继承父元素的所有计数器。否则,该元素必须有一组空的计数器。然后该元素从文档顺序中的前一个元素继承计数器值。


为什么没有 div 的代码段有效?

在工作片段(没有 的片段div)中,会发生以下情况:

  • counter.h1(添加前缀以区别于元素)在创建(或重置)时body,其初始值设置为 0。
  • 所有元素都继承其父级的计数器,因此其中的每个元素都body获取counter.h1。当h1遇到第一个元素时,值counter.h1递增到 1。h1遇到下一个时,它从前一个元素继承计数器值,然后递增到 2。
  • counter.h2counter 在h1element 处创建,value 设置为 0。该值对 the 的兄弟姐妹可见,h1并且它们都可以继承它。
  • 在这个片段中,所有h2元素实际上都是元素的兄弟姐妹,h1因此每个h2元素都继承counter.h2了已经在 at 创建的元素,h1并且只是增加了它的值。因此,当h2遇到第一个时counter.h2变为 1,依此类推。
  • h2与元素类似,元素h3也是h1andh2元素的兄弟,因此它们也继承counter.h1and counter.h2。这就是此示例中编号保持正确的原因。

body {counter-reset: h1}
h1 {counter-reset: h2}
h2 {counter-reset: h3}
h1:before {counter-increment: h1; content: counter(h1)". "}
h2:before {counter-increment: h2; content: counter(h1)"." counter(h2)". "}
h3:before {counter-increment: h3; content: counter(h1)"." counter(h2)"." counter(h3)". "}
<!-- body creates counter.h1 and set to 0 -->
<h1>Heading 1 <!-- Inherits counter.h1 from parent, creates counter.h2 and set to 0 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h1 to 1 and displays value -->
</h1>
<p>Paragraph</p>
<h2>Heading 2 <!-- Inherits counter.h1, counter.h2 from sibling, creates counter.h3 and set to 0 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h2 to 1 and displays value -->
</h2>
<p>Paragraph</p>
<h3>Heading 3 <!-- Inherits counter.h1, counter.h2, counter.h3 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h3 to 1 and displays value -->
</h3>
<p>Paragraph</p>
<h3>2nd Heading 3 <!-- Inherits counter.h1, counter.h2, counter.h3 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h3 to 2 and displays value -->  
</h3>
<p>Paragraph</p>
<h2>2nd Heading 2 <!-- Inherits counter.h1, counter.h2, counter.h3, resets counter.h3 to 0 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h2 to 2 and displays value -->
</h2>
<p>Paragraph</p>
<h2>3rd Heading 2 <!-- Inherits counter.h1, counter.h2, counter.h3, resets counter.h3 to 0 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h2 to 3 and displays value -->
</h2>
<p>Paragraph</p>
<h1>2nd Heading 1 <!-- Inherits counter.h1, counter.h2, counter.h3, resets counter.h2 to 0 -->
  <!-- ::before being a child inherits all counters from parent, increments counter.h1 to 2 and displays value -->
</h1>


为什么带有 div 的片段不起作用?

现在让我们来看一下不起作用的片段(h1a 中存在的片段div)。

  • 在这里,h1创建counter.h2,但这只能由h1(其中没有)的兄弟姐妹继承。
  • 每当h2遇到一个元素时,UA 都会尝试增加选择器counter.h2中的值:before。但是在这里,h2父母没有继承counter.h2,因此h2:before也没有。因为这h2:before将创建自己的counter.h2并递增到 1。
  • 后续h2元素也不能继承counter.h2,因为计数器是由h2:before(它是 的子级h2)创建的。因此,每次h2遇到 a 时,都会在其内部创建一个新计数器:before并递增。这就是为什么所有h2显示为1.1
  • 同样,没有一个h3元素知道counter.h2并且它们也不增加它,这就是它们显示为1.0.x的原因。
  • 但是,它们都可以继承counter.h3,因为它是由h2元素创建的,该元素是所有元素的兄弟h3。这就是counter.h3正确递增的原因。

body {counter-reset: h1}
h1 {counter-reset: h2}
h2 {counter-reset: h3}
h1:before {counter-increment: h1; content: counter(h1)". "}
h2:before {counter-increment: h2; content: counter(h1)"." counter(h2)". "}
h3:before {counter-increment: h3; content: counter(h1)"." counter(h2)"." counter(h3)". "}
<!-- body creates counter.h1, sets it to 0 -->
<div class="test"> <!-- Inherits counter.h1 from parent -->
  <h1>Heading 1 <!-- Again inherits counter.h1 from parent, creates counter.h2 -->
    <!-- ::before increments counter.h1 to 1 and display value-->
  </h1>
</div>
<p>Paragraph</p>
<h2>Heading 2 <!-- Inherits counter.h1 as it is from parent but not counter.h2, creates counter.h3 -->
  <!-- ::before has no counter.h2, so creates a counter.h2 and increments to 1 -->
</h2>
<p>Paragraph</p>
<h3>Heading 3 <!-- Inherits counter.h1 as it is from parent, couunter.h3 from sibling but not counter.h2 -->
  <!-- ::before inherits counter.h3 from parent and increments to 1, has no counter.h2 so creates a new counter.h2 and sets to 0 -->
</h3>
<p>Paragraph</p>
<h3>2nd Heading 3 <!-- Inherits counter.h1 as it is from parent, couunter.h3 from sibling but not counter.h2 -->
  <!-- ::before inherits counter.h3 from parent and increments to 2, has no counter.h2 so creates a new counter.h2 and sets to 0 -->
</h3>
<p>Paragraph</p>
<h2>2nd Heading 2 <!-- Inherits counter.h1 as it is from parent, couunter.h3 from sibling but not counter.h2, resets counter.h3 to 0 -->
  <!-- ::before has no counter.h2, so creates a counter.h2 and increments to 1 -->
</h2>
<p>Paragraph</p>
<h2>3rd Heading 2 <!-- Inherits counter.h1 as it is from parent, couunter.h3 from sibling but not counter.h2, resets counter.h3 to 0 -->
  <!-- ::before has no counter.h2, so creates a counter.h2 and increments to 1 -->
</h2>
<p>Paragraph</p>
<h1>2nd Heading 1 <!-- Inherits counter.h1 as it is from parent, couunter.h3 from sibling but not counter.h2, resets counter.h2 to 0 -->
  <!-- ::before inherits counter.h1 from parent and increments to 2 -->
</h1>


解决办法是什么?

这个问题的理想解决方案是首先在 body 本身重置所有 3 个计数器,以便所有元素都知道计数器的存在并可以继承或使用它的值。

body {counter-reset: h1 h2 h3}
h1 {counter-reset: h2 h3}
h2 {counter-reset: h3}
h1:before {counter-increment: h1; content: counter(h1)". "}
h2:before {counter-increment: h2; content: counter(h1)"." counter(h2)". "}
h3:before {counter-increment: h3; content: counter(h1)"." counter(h2)"." counter(h3)". "}
<!-- body creates counter.h1, counter.h2, counter.h3 sets all 0 -->
<div class="test"> <!-- Inherits all 3 counters -->
  <h1>Heading 1 <!-- Inherits all 3 counters, resets counter.h2 and counter.h3 to 0 -->
    <!-- ::before also inherits all 3 counters, increments counter.h1 to 1 and displays value -->
  </h1>
</div>
<p>Paragraph</p>
<h2>Heading 2 <!-- Inherits all 3 counters, resets counter.h3 to 0 -->
  <!-- ::before also inherits all 3 counters, increments counter.h2 to 1 and displays value -->
</h2>
<p>Paragraph</p>
<h3>Heading 3 <!-- Inherits all 3 counters -->
  <!-- ::before also inherits all 3 counters, increments counter.h3 to 1 and displays value -->
</h3>
<p>Paragraph</p>
<h3>2nd Heading 3 <!-- Inherits all 3 counters -->
  <!-- ::before also inherits all 3 counters, increments counter.h3 to 2 and displays value -->
</h3>
<p>Paragraph</p>
<h2>2nd Heading 2 <!-- Inherits all 3 counters, resets counter.h3 to 0 -->
  <!-- ::before also inherits all 3 counters, increments counter.h2 to 2, resets counter.h3 to 0 and displays value -->
</h2>
<p>Paragraph</p>
<h2>3rd Heading 2 <!-- Inherits all 3 counters, resets counter.h3 to 0 -->
  <!-- ::before also inherits all 3 counters, increments counter.h2 to 3, resets counter.h3 to 0 and displays value -->
</h2>
<p>Paragraph</p>
<h1>2nd Heading 1 <!-- Inherits all 3 counters, resets counter.h2 and counter.h3 to 0 -->
  <!-- ::before also inherits all 3 counters, increments counter.h1 to 2, resets counter.h2, counter.h3 to 0 and displays value -->
</h1>

于 2015-07-27T18:11:54.963 回答
5

考虑一下(与您的结构非常相似,只是更简单一些):

body {
  counter-reset: h1;
}

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

h2:before {
  content: counter(h1) "." counter(h2) ". ";
  counter-increment: h2;
}
<div>
  <h1>Heading first level 1</h1>
</div>
  <h2>Heading second level 1</h2>
  <h2>Heading second level 2</h2>
  <h2>Heading second level 3</h2>
  <h2>Heading second level 4</h2>
  <h2>Heading second level 5</h2>    
<h1>Heading first level 2</h1>
  <h2>Test</h2>
  <h2>Test</h2>
  <h2>Test</h2>
<h1>Heading first level 3</h1>
<h1>Heading first level 4</h1>

为什么您的布局不起作用

根据推荐:

计数器是“自嵌套”的,从某种意义上说,重置后代元素或伪元素中的计数器会自动创建计数器的新实例。这对于像 HTML 中的列表这样的情况很重要,其中元素可以嵌套到任意深度。

您的布局中的问题是第一个<h1>内部初始化了一个单独的计数器<div>实例。h1发生这种情况是因为计数器对嵌套元素很敏感。每次重置不同级别的计数器时,都不会影响范围为另一个级别的相同计数器实例!

怎么了

以下是发生的情况:

01. <body>                             | h1 = *
02. <div>                              |
03.   <h1>Heading first level 1</h1>   | h1 = 1 |  div-h2 = *
04. </div>                             |
05.   <h2>Heading second level 1</h2>  |        | h2 = 1
06.   <h2>Heading second level 2</h2>  |        | h2 = 1
07.   <h2>Heading second level 3</h2>  |        | h2 = 1
08.   <h2>Heading second level 4</h2>  |        | h2 = 1
09.   <h2>Heading second level 5</h2>  |        | h2 = 1
10. <h1>Heading first level 2</h1>     | h1 = 2 | h2 = *
11.   <h2>Test</h2>                    |        | h2 = 1
12.   <h2>Test</h2>                    |        | h2 = 2
13.   <h2>Test</h2>                    |        | h2 = 3
14. <h1>Heading first level 3</h1>     | h1 = 3
15. <h1>Heading first level 4</h1>     | h1 = 4

如您所见,我们重置了工作正常的01.计数器。h1但是在h1元素中我们重置了 counter h2

问题出现在我们在嵌套级别03.重置计数器的位置,为了澄清这一点,我称之为计数器:。事实上,从to的下一个元素正在使用另一个尚未重置的计数器!那是计数器(没有嵌套),即使他们尝试增加它,也没有什么可以增加的,因为重置是强制性的!h2divdiv-h2h205.09.h2

我们10.没有div嵌套,因此计数器h2被正确重置,因此也增加了。

该怎么办

在您的情况下,您必须避免在页面中生成不均匀的嵌套结构。这是一个干净的 HTML 的建议,在你的情况下,如果你真的需要保留那个 div,只需div在你重置计数器的地方添加一个选择器h2

div {
  counter-reset: h2;
}

所以这是最终的工作片段:

body {
  counter-reset: h1;
}

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

div {
  counter-reset: h2;
}

h2:before {
  content: counter(h1) "." counter(h2) ". ";
  counter-increment: h2;
}
<div>
  <h1>Heading first level 1</h1>
</div>
  <h2>Heading second level 1</h2>
  <h2>Heading second level 2</h2>
  <h2>Heading second level 3</h2>
  <h2>Heading second level 4</h2>
  <h2>Heading second level 5</h2>    
<h1>Heading first level 2</h1>
  <h2>Test</h2>
  <h2>Test</h2>
  <h2>Test</h2>
<div>
  <h1>Heading first level 1</h1>
</div>
  <h2>Test</h2>
  <h2>Test</h2>
  <h2>Test</h2>
<h1>Heading first level 3</h1>
<h1>Heading first level 4</h1>

div如果您只有那些嵌套 for ,则上述解决方案有效h1,以防您希望将其他标题元素包装到divs 中,而不是您也需要在h3那里重置计数器!但我不推荐这样做,因为它是一种非常混乱的 CSS 安排:难以维护且不易遵循。

记住在 CSS 中总有一种方法可以实现,你说你需要那个div,但我认为你没有尝试所有的可能性来摆脱它。

于 2015-07-27T16:40:47.340 回答