HTML有序列表1.1、1.2(嵌套计数器和作用域)无法工作。

122

我使用嵌套计数器和作用域创建有序列表:

ol {
    counter-reset: item;
    padding-left: 10px;
}
li {
    display: block
}
li:before {
    content: counters(item, ".") " ";
    counter-increment: item
}
<ol>
    <li>one</li>
    <li>two</li>
    <ol>
        <li>two.one</li>
        <li>two.two</li>
        <li>two.three</li>
    </ol>
    <li>three</li>
    <ol>
        <li>three.one</li>
        <li>three.two</li>
        <ol>
            <li>three.two.one</li>
            <li>three.two.two</li>
        </ol>
    </ol>
    <li>four</li>
</ol>

我期望以下结果:

1. one
2. two
  2.1. two.one
  2.2. two.two
  2.3. two.three
3. three
  3.1 three.one
  3.2 three.two
    3.2.1 three.two.one
    3.2.2 three.two.two
4. four

相反,我看到的是(错误编号)

1. one
2. two
  2.1. two.one
  2.2. two.two
  2.3. two.three
2.4 three <!-- this is where it goes wrong, when going back to the parent -->
  2.1 three.one
  2.2 three.two
    2.2.1 three.two.one
    2.2.2 three.two.two
2.3 four

我一无所知,有没有人看到哪里出了问题?

这是一个JSFiddle:http://jsfiddle.net/qGCUk/2/

10个回答

132

取消 "标准化CSS" 的勾选 - http://jsfiddle.net/qGCUk/3/ 在此使用的CSS重置会将所有列表的边距和填充都默认为0。

更新 http://jsfiddle.net/qGCUk/4/ - 你必须将子列表包含在主要的<li>中。

ol {
  counter-reset: item
}
li {
  display: block
}
li:before {
  content: counters(item, ".") " ";
  counter-increment: item
}
<ol>
  <li>one</li>
  <li>two
    <ol>
      <li>two.one</li>
      <li>two.two</li>
      <li>two.three</li>
    </ol>
  </li>
  <li>three
    <ol>
      <li>three.one</li>
      <li>three.two
        <ol>
          <li>three.two.one</li>
          <li>three.two.two</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>four</li>
</ol>


4
如何使索引的标号变成带点的格式,例如从1.变成1.1.1.2.1.3.等等? - URL87
2
请确保修复CSS选择器,以免影响导航列表等内容。 - Okomikeruko
@Okomikeruko “修复 CSS 选择器” 是什么意思?因为我遇到了你提到的问题 - 这个技巧不仅影响了我要使用它的有序列表,还影响了我的 HTML 中的其他列表。 :-\算了吧:Moshe Simantov 的答案解决了这个问题。 :) - antred
2
@antred元素属性,如 idclass,允许您使用选择器定义特定于这些元素的CSS。如果您使用一个通用的 liulol 等,则CSS会影响所有实例。但是,如果您将元素设置为 <ol class="cleared"> 并将CSS选择器设置为 ol.cleared,则不会不必要地影响其他 ol 元素。 - Okomikeruko
这里为什么要使用li display: block? - Joel Peltonen
这种方法太丑陋了,而且很不专业。这种方法甚至不能保持数字右侧的文本;文本会在第一行后面跟着数字。虽然这不是你的错,但CSS没有开箱即用的解决方案真是令人失望。 - Paul Chris Jones

79

使用这个样式仅改变嵌套列表:

ol {
    counter-reset: item;
}

ol > li {
    counter-increment: item;
}

ol ol > li {
    display: block;
}

ol ol > li:before {
    content: counters(item, ".") ". ";
    margin-left: -20px;
}

2
太棒了!对我来说直接拿来就能用!谢啦。 - yO_
3
这是最佳答案,因为它还具有第一级带有点和插入内容。 - Martin Eckleben
如果我在 ol ol > li:before 中添加 font-weight: bold,则嵌套列表的计数器会变为 bold,但不会使第一级列表的计数器变为 bold - Sushmit Sagar
为了让这个工作对我来说更整齐,我不得不在“:before”中添加“float:left;”。 - James Nisbet
1
十年后仍然有用。谢谢。 - DoomBot

16

看一下这个:

http://jsfiddle.net/PTbGc/

你的问题似乎已经解决。


在我这里(在Chrome和Mac OS X下)会显示什么:

1. one
2. two
  2.1. two.one
  2.2. two.two
  2.3. two.three
3. three
  3.1 three.one
  3.2 three.two
    3.2.1 three.two.one
    3.2.2 three.two.two
4. four

我是如何做到的


不要:

<li>Item 1</li>
<li>Item 2</li>
   <ol>
        <li>Subitem 1</li>
        <li>Subitem 2</li>
   </ol>

做:

<li>Item 1</li>
<li>Item 2
   <ol>
        <li>Subitem 1</li>
        <li>Subitem 2</li>
   </ol>
</li>

8

这是一个很好的解决方案!通过添加一些CSS规则,您可以将其格式化为像MS Word大纲列表一样,并具有悬挂式首行缩进:

OL { 
  counter-reset: item; 
}
LI { 
  display: block; 
}
LI:before { 
  content: counters(item, ".") "."; 
  counter-increment: item; 
  padding-right:10px; 
  margin-left:-20px;
}

2
这种方法的问题在于您无法复制列表编号。因此,如果您复制了一个非常庞大的列表,则其编号将不会被包含在内。 - Rohit
太棒了!正是我在寻找的!! - Bat

7

保持简单!

这是一个更简单和标准的解决方案,用于增加数字并保留末尾的小数点。
即使您已正确编写CSS,如果HTML不正确,则它也无法正常工作。请参见以下内容。

CSS

ol {
  counter-reset: item;
}
ol li {
  display: block;
}
ol li:before {
  content: counters(item, ". ") ". ";
  counter-increment: item;
}

SASS

ol {
    counter-reset: item;
    li {
        display: block;
        &:before {
            content: counters(item, ". ") ". ";
            counter-increment: item
        }
    }
}

HTML 父子关系

如果您想添加一个子元素,请确保它是在父元素li内部。

不起作用 ✘

请注意这里父元素li和子元素ol li是分开的,这样是行不通的。

<ol>
    <li>Parent 1</li> <!-- Parent has open and close li tags -->
    <ol> 
        <li>Child</li>
    </ol>
    <li>Parent 2</li>
</ol>

可行 ✔

您需要将ol li子元素放置在父级li中。请注意,父级li与子元素紧密相连。

<ol>

    <li>Parent 1 <!-- Parent open li tag -->
        <ol> 
            <li>Child</li>
        </ol>
    </li> <!-- Parent close li tag -->

    <li>Parent 2</li>
</ol>

6
我认为这些答案过于复杂了。如果你不需要支持Internet Explorer,那么解决方案只需要一行代码:

ol > li::marker { content: counters(list-item, '.') '. '; }
<ol>
    <li>one</li>
    <li>two</li>
    <ol>
        <li>two.one</li>
        <li>two.two</li>
        <li>two.three</li>
    </ol>
    <li>three</li>
    <ol>
        <li>three.one</li>
        <li>three.two</li>
        <ol>
            <li>three.two.one</li>
            <li>three.two.two</li>
        </ol>
    </ol>
    <li>four</li>
</ol>

请参阅 MDN CSS 参考网站上的 ::marker 伪元素页面 使用 CSS 计数器页面以获得更多信息。

3

在查看其他答案后,我得出了以下结论,只需将类nested-counter-list应用于根ol标签:

Sass 代码:

ol.nested-counter-list {
  counter-reset: item;

  li {
    display: block;

    &::before {
      content: counters(item, ".") ". ";
      counter-increment: item;
      font-weight: bold;
    }
  }

  ol {
    counter-reset: item;

    & > li {
      display: block;

      &::before {
        content: counters(item, ".") " ";
        counter-increment: item;
        font-weight: bold;
      }
    }
  }
}

CSS 代码:

ol.nested-counter-list {
  counter-reset: item;
}
ol.nested-counter-list li {
  display: block;
}
ol.nested-counter-list li::before {
  content: counters(item, ".") ". ";
  counter-increment: item;
  font-weight: bold;
}
ol.nested-counter-list ol {
  counter-reset: item;
}
ol.nested-counter-list ol > li {
  display: block;
}
ol.nested-counter-list ol > li::before {
  content: counters(item, ".") " ";
  counter-increment: item;
  font-weight: bold;
}

ol.nested-counter-list {
  counter-reset: item;
}

ol.nested-counter-list li {
  display: block;
}

ol.nested-counter-list li::before {
  content: counters(item, ".") ". ";
  counter-increment: item;
  font-weight: bold;
}

ol.nested-counter-list ol {
  counter-reset: item;
}

ol.nested-counter-list ol>li {
  display: block;
}

ol.nested-counter-list ol>li::before {
  content: counters(item, ".") " ";
  counter-increment: item;
  font-weight: bold;
}
<ol class="nested-counter-list">
  <li>one</li>
  <li>two
    <ol>
      <li>two.one</li>
      <li>two.two</li>
      <li>two.three</li>
    </ol>
  </li>
  <li>three
    <ol>
      <li>three.one</li>
      <li>three.two
        <ol>
          <li>three.two.one</li>
          <li>three.two.two</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>four</li>
</ol>

如果您需要在嵌套列表的计数器末尾添加 .,请使用以下内容:

ol.nested-counter-list {
  counter-reset: item;
}

ol.nested-counter-list li {
  display: block;
}

ol.nested-counter-list li::before {
  content: counters(item, ".") ". ";
  counter-increment: item;
  font-weight: bold;
}

ol.nested-counter-list ol {
  counter-reset: item;
}
<ol class="nested-counter-list">
  <li>one</li>
  <li>two
    <ol>
      <li>two.one</li>
      <li>two.two</li>
      <li>two.three</li>
    </ol>
  </li>
  <li>three
    <ol>
      <li>three.one</li>
      <li>three.two
        <ol>
          <li>three.two.one</li>
          <li>three.two.two</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>four</li>
</ol>


1

我最近遇到了类似的问题。解决方法是将有序列表中li项的display属性设置为list-item,而不是display block,并确保ol的display属性不是list-item。即

li { display: list-item;}

使用这个方法,HTML解析器会将所有的li视为列表项并分配相应的值,并根据您的设置将ol视为内联块或块元素,并不尝试为其分配任何计数值。

这会导致编号重复。 - TylerH

1

Moshe的解决方案非常好,但如果您需要将列表放在div内部,则问题可能仍然存在。(阅读:嵌套列表上的CSS counter-reset

这种样式可以避免这个问题:

ol > li {
    counter-increment: item;
}

ol > li:first-child {
  counter-reset: item;
}

ol ol > li {
    display: block;
}

ol ol > li:before {
    content: counters(item, ".") ". ";
    margin-left: -20px;
}
<ol>
  <li>list not nested in div</li>
</ol>

<hr>

<div>
  <ol>
  <li>nested in div</li>
  <li>two
    <ol>
      <li>two.one</li>
      <li>two.two</li>
      <li>two.three</li>
    </ol>
  </li>
  <li>three
    <ol>
      <li>three.one</li>
      <li>three.two
        <ol>
          <li>three.two.one</li>
          <li>three.two.two</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>four</li>
  </ol>
</div>

你也可以在 li:before 上设置计数器重置。

如果我只想在根列表中去除尾部的 . 而不是嵌套列表中的呢? - Sushmit Sagar

0

感谢以上所有人的回答!

由于我需要RTL解决方案,我发现这个可以解决:

ol.nested-counter-list li {
  display: block;
  unicode-bidi: bidi-override;
}

因此,您可以使用上述任何解决方案,但还需要针对RTL情况更新特定的CSS选择器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接