有没有办法用CSS将有序列表的格式改为像“1.1、1.2、1.3”这样的形式,而不是只有数字“1、2、3”?

265
使用CSS,有没有办法让有序列表的项目看起来像1.1、1.2、1.3(而不仅仅是1、2、3…)?目前为止,使用list-style-type:decimal只能得到1、2、3,而不能得到1.1、1.2、1.3。

2
我建议将被接受的答案与Jakub Jirutka的答案进行比较,我认为后者甚至更好。 - Frank Conijn - Support Ukraine
优雅的解决方案。有什么想法为什么维基百科在其内容部分使用ul而不是这个? - Mattypants
1
@davnicwil 我同意;看起来九月份我可能只是错误地应用了重复命令。 - TylerH
太酷了,现在我感到很尴尬,因为我从未想过它可能只是一个简单的错误 - 抱歉! - davnicwil
13个回答

360

您可以使用counters来实现:

The following style sheet numbers nested list items as "1", "1.1", "1.1.1", etc.

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

例子

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

请参阅嵌套计数器和作用域以获取更多信息。


2
很棒的答案。这方面有支持吗? - Jason McCreary
1
@Jason McCreary:好吧,这就是缺点:计数器在IE 8之前的版本中不受支持 - Gumbo
3
这个解决方案漏掉了一个小细节:项目编号后面的点。这看起来不像标准的列表样式。通过在 li:before 的规则中添加一个点来修复:content: counters(item, ".")". "; - Mr. Lance E Sloan
4
这个回答很差,无法正常工作。请查看下面Jakub Jirutka的答案。 - Mr Pablo
1
@Gumbo 我知道,Jakub的回答给了我正确的编号。 - Mr Pablo
显示剩余7条评论

345
这个页面上的解决方案都不能正确地适用于所有级别和长(换行)段落。由于标记的大小不同(1.,1.2,1.10,1.10.5,...),要实现一致的缩进真的很棘手;它不能仅仅“伪造”,甚至不能为每个可能的缩进级别预先计算边距/填充。

我终于找到了一个解决方案,它实际上是有效的,并且不需要任何JavaScript。

已在Firefox 32、Chromium 37、IE 9和Android浏览器上进行了测试。在IE 7及以前的版本上无效。

CSS:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;    
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") " ";
}

示例: 示例

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;
}

li li {
  margin: 0;
}

li li:before {
  content: counters(item, ".") " ";
}
<ol>
  <li>Lorem ipsum.</li>
  <li>Excepteur sint occaecat cupidatat non proident:
    <ol>
      <li>sunt in culpa qui officia,</li>
      <li>deserunt mollit anim id est laborum.</li>
    </ol>
  </li>
  <li>Ut enim ad minim veniam.
    <ol>
      <li>Quis nostrud exercitation.</li>
      <li>Ullamco laboris nisi ut.
        <ol>
          <li>
            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
          </li>
        </ol>
      </li>
    </ol>
  </li>
  <li>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia
    animi.</li>
</ol>

试试在JSFiddle上运行它,在Gist上进行分叉。

2
做得好,达到这种缩进方式。然而我仍然认为您列出的前两种缩进方式是一种偏好而非对错之分。请考虑第一种情况第二种情况——后者可以在空间变得难处理之前挤入更多级别,同时看起来还很整齐。此外,微软字处理软件和默认浏览器样式都使用第二种缩进方式。我猜它们也是在做错事吗? - slightlyfaulty
5
从技术上讲,它确实适用于所有级别和长段落。如果使用十几个级别是合理的,那就是另一个问题,与技术解决方案无关。关键是你不必像其他解决方案那样为每个嵌套级别预定义CSS规则。 - Jakub Jirutka
5
虽然我不会说其他回答本质上有什么“错误”,但我会说它们是不完整的。这个回答是准确无误的,甚至还适用于我正在修改的一个可怕奇怪风格的网站。 - DanielM
2
@tremby:可以通过将li使用"display: table-row"而不是"display: table"来解决差异。这样带来的问题是,li不能使用任何边距/填充,因为表行始终由其内容自动调整大小。可以通过添加一个具有"display: block"的"li:after"来解决这个问题。请参见jsFiddle以获取完整示例。额外的奖励是我在"li:before"中添加了"text-align: right",使数字右对齐。 - mmlr
4
好的解决方案。我在 ol > li:before 中添加了 white-space: nowrap; 以防止数字换行。 - Maxim
显示剩余5条评论

75
所选答案是一个很好的起点,但它基本上强制对列表项进行list-style-position: inside;样式设置,使换行文本难以阅读。这里有一个简单的解决方法,还可以控制数字和文本之间的间距,并按照默认行为将数字右对齐。
ol {
    counter-reset: item;
}
ol li {
    display: block;
    position: relative;
}
ol li:before {
    content: counters(item, ".")".";
    counter-increment: item;
    position: absolute;
    margin-right: 100%;
    right: 10px; /* space between number and text */
}

JSFiddle: http://jsfiddle.net/3J4Bu/


1
一个缺点是它会在每个列表项的末尾添加一个句号。 - Davin Studer
4
它只是在每个数字末尾添加一个句号,与默认的ol行为相同。可以通过从“content”属性中删除最后一个“。”来轻松删除它,但这样看起来有点奇怪。 - slightlyfaulty

21

这里发布的解决方案对我来说效果不佳,因此我将本问题和以下问题的解决方案混合使用:是否可以在HTML中创建多级有序列表?

/* Numbered lists like 1, 1.1, 2.2.1... */
ol li {display:block;} /* hide original list counter */
ol > li:first-child {counter-reset: item;} /* reset counter */
ol > li {counter-increment: item; position: relative;} /* increment counter */
ol > li:before {content:counters(item, ".") ". "; position: absolute; margin-right: 100%; right: 10px;} /* print counter */

结果:

screenshot

注:如果您想查看源代码或其他内容,请参阅此帖子的屏幕截图:http://estiloasertivo.blogspot.com.es/2014/08/introduccion-running-lean-y-lean.html


这个解决方案在9个列表项后看起来很好,因为其他方案在2位数字上存在一些间距问题。谢谢。 - Lahiru Pinto
我最初点赞了这个答案,但后来注意到在Chrome中出现了渲染问题。这是间歇性的,并且似乎发生在列表更下面的地方,其中计数器由于某种原因没有重置。在一个视图上可能没问题,刷新后数字会长时间未重置。不知道为什么。Jakub的答案对我有用。 - crdunst

8
注意:在现代浏览器中,使用CSS计数器(counters)可以创建嵌套编号。请参见被接受的答案。以下内容仅供历史兴趣。
如果浏览器支持contentcounter

.foo {
  counter-reset: foo;
}
.foo li {
  list-style-type: none;
}
.foo li::before {
  counter-increment: foo;
  content: "1." counter(foo) " ";
}
<ol class="foo">
  <li>uno</li>
  <li>dos</li>
  <li>tres</li>
  <li>cuatro</li>
</ol>


当列表嵌套时,这个解决方案会失败得很惨。 - Mr. Lance E Sloan
@LS 您可以根据需要随时调整选择器。.foo > ol > li - kennytm
2
我的观点是,您已经将“1.”硬编码到样式中。当子列表是父列表中第二项的子项时会发生什么?你希望它显示为“2.”,但由于代码在这里的方式而始终为“1.”。解决方案是什么?为每个可能的数字创建新的样式集吗?不需要。请使用counters()函数,而不是counter()函数,就像上面的示例一样。 - Mr. Lance E Sloan

6
在不久的将来,您可能能够使用 ::marker 伪元素 来实现其他解决方案所需的同样效果,只需一行代码即可。请注意查看 浏览器兼容性表,因为这仍然是一项实验性技术。截至撰写本文时,只有 Firefox 和 Firefox for Android(从版本68开始)支持此功能。

Here is a snippet that will render correctly if tried in a compatible browser:

::marker { content: counters(list-item,'.') ':' }
li { padding-left: 0.5em }
<ol>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
  <li>li element</li>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
</ol>

您可能还想查看这个由smashingmagazine提供的优秀文章,涉及该主题。


5
以下方法对我有效:
ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ") ";
  display: table-cell;
  padding-right: 0.6em;
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") ") ";
}

看这个:http://jsfiddle.net/rLebz84u/2/ 或者这个:http://jsfiddle.net/rLebz84u/3/ 其中有更多的文本,并且已经对齐。

2

当有两个列表且第二个列表位于 DIV 中时,我遇到了一些问题。 第二个列表应该从 1 开始,而不是 2.1。

<ol>
    <li>lorem</li>
    <li>lorem ipsum</li>
</ol>

<div>
    <ol>
        <li>lorem (should be 1.)</li>
        <li>lorem ipsum ( should be 2.)</li>
    </ol>
</div>

http://jsfiddle.net/3J4Bu/364/

编辑: 我通过这个http://jsfiddle.net/hy5f6161/解决了问题。


2
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="author" content="Sandro Alvares - KingRider">
    </head>
    <body>
        <style type="text/css">
            li.title { 
                font-size: 20px; 
                font-weight: lighter; 
                padding: 15px; 
                counter-increment: ordem; 
            }
            .foo { 
                counter-reset: foo; 
                padding-left: 15px; 
            }
            .foo li { 
                list-style-type: none; 
            }
            .foo li:before { 
                counter-increment: foo; 
                content: counter(ordem) "." counter(foo) " "; 
            }
        </style>
        <ol>
            <li class="title">TITLE ONE</li>
            <ol class="foo">
                <li>text 1 one</li>
                <li>text 1 two</li>
                <li>text 1 three</li>
                <li>text 1 four</li>
            </ol>
            <li class="title">TITLE TWO</li>
            <ol class="foo">
                <li>text 2 one</li>
                <li>text 2 two</li>
                <li>text 2 three</li>
                <li>text 2 four</li>
            </ol>
            <li class="title">TITLE THREE</li>
            <ol class="foo">
                <li>text 3 one</li>
                <li>text 3 two</li>
                <li>text 3 three</li>
                <li>text 3 four</li>
            </ol>
        </ol>
    </body>
</html>

Result: http://i.stack.imgur.com/78bN8.jpg


1

如果你想要对第一个子级li进行其他CSS的调整,以下是正确的代码。

<style>
    li.title { 
        font-size: 20px; 

        counter-increment: ordem; 
        color:#0080B0;
    }
    .my_ol_class { 
        counter-reset: my_ol_class; 
        padding-left: 30px !important; 
    }
    .my_ol_class li { 
          display: block;
        position: relative;

    }
    .my_ol_class li:before { 
        counter-increment: my_ol_class; 
        content: counter(ordem) "." counter(my_ol_class) " "; 
        position: absolute;
        margin-right: 100%;
        right: 10px; /* space between number and text */
    }
    li.title ol li{
         font-size: 15px;
         color:#5E5E5E;
    }
</style>

在HTML文件中。
        <ol>
            <li class="title"> <p class="page-header list_title">Acceptance of Terms. </p>
                <ol class="my_ol_class">
                    <li> 
                        <p>
                            my text 1.
                        </p>
                    </li>
                    <li>
                        <p>
                            my text 2.
                        </p>
                    </li>
                </ol>
            </li>
        </ol>

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