只使用 CSS 在 pre 上创建行号

我尝试样式代码前框与行号前面的每一行。我更喜欢只用 CSS 来做。这就是我所做的

pre {
background: #303030;
color: #f1f1f1;
padding: 10px 16px;
border-radius: 2px;
border-top: 4px solid #00aeef;
-moz-box-shadow: inset 0 0 10px #000;
box-shadow: inset 0 0 10px #000;
}
pre span {
display: block;
line-height: 1.5rem;
}
pre span:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid #ddd;
padding: 0 .5em;
margin-right: .5em;
color: #888
}
<pre>
<span>lorem ipsum</span>
<span>&gt;&gt; lorem ipsum</span>
<span>lorem ipsum,\ </span>
<span>lorem ipsum.</span>
<span>&gt;&gt; lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
</pre>

但是,所有的线都有数字1。增量不起作用。这是一个 Jsfiddle

  1. 我做错了什么?
  2. 什么是浏览器兼容这个 CSS 唯一的解决方案?
28459 次浏览

为什么计数器不增加?

您没有在父标记级别重置或创建计数器。如果将以下代码行添加到 pre选择器,则代码将正常工作。如果不在父级别创建计数器(使用 counter-reset) ,每个元素将创建自己的计数器,然后递增。

counter-reset: line;

什么时候创建计数器?

来自 W3C 规范:

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

计数器集和计数器增量属性操作现有计数器的值。

在这种情况下,我们没有使用 counter-reset属性创建计数器,因此 span:before伪元素选择器中的 counter-increment属性将创建给定名称的计数器并递增它。


计数器如何知道当前值?

来自 W3C 规范的报道:

如果一个元素有以前的同级元素,则为 必须继承兄弟计数器的所有计数器。否则,如果元素有父元素,则为 < strong > 必须继承父类的所有计数器 。否则,元素必须有一组空计数器。

然后是元素 < strong > 按照文档顺序 从前面的元素继承计数器值

这里,由于计数器只是在伪元素中创建的,因此它的父元素(span)不知道它的创建,所以这个 span的兄弟元素不会继承计数器。因为它甚至不继承任何计数器,所以它也不从前面的元素获取当前值。


为什么在父级上创建计数器会起作用?

当在 pre标记级别创建计数器时,计数器会传递给它的每个子元素(即每个 span,然后每个 span:before会知道或继承这个计数器) ,现在 span:before中的递增语句只会递增它从父元素获得的计数器的值。

现在,由于每个 span从它的前一个兄弟继承 line计数器,它们也将从文档顺序中的前一个元素继承当前值,因此它将从1继承到2,3等等。


为什么在跨度或前期使用反增量?

正如您所猜测的,当没有现有的计数器时,反增量属性 创造是一个新的计数器,因此在 span上添加 counter-increment: line将在遇到的第一个跨度上创建一个计数器。现在,由于 span的每个兄弟继承这个计数器,因此它不会每次都创建一个新的计数器,而只是继承前一个元素的值。因此,这种方法是可行的,但是最好使用 counter-reset语句显式地创建计数器。


浏览器支持如何?

对 CSS 计数器的浏览器支持令人难以置信的好,这在 CSS 和 对它的支持甚至在 IE8中也是可用的中并不新鲜。


演示:

pre {
background: #303030;
color: #f1f1f1;
padding: 10px 16px;
border-radius: 2px;
border-top: 4px solid #00aeef;
-moz-box-shadow: inset 0 0 10px #000;
box-shadow: inset 0 0 10px #000;
counter-reset: line;
}
pre span {
display: block;
line-height: 1.5rem;
}
pre span:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid #ddd;
padding: 0 .5em;
margin-right: .5em;
color: #888
}
<pre><span>lorem ipsum</span>
<span>&gt;&gt; lorem ipsum</span>
<span>lorem ipsum,\ </span>
<span>lorem ipsum.</span>
<span>&gt;&gt; lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
</pre>

你必须在你的范围内增加 line:

pre span {
display: block;
line-height: 1.5rem;
counter-increment: line;
}

看看这个更新的 Jsfiddle

你好,你需要重置计数器上一个/更高的加载项目,检查 https://jsfiddle.net/n2xkgt7s/2/ pre { counter-reset: line; }

取代 <pre>,你可以考虑有序列表 <ol>,它已经提供了正确对齐的编号(当数字跳跃时更好,例如9-> 10)。 <li>也不需要结束标记 </li>(https://html.spec.whatwg.org/multipage/syntax.html#optional-tags) ,这样可以节省输入。

ol {
font-family: monospace;
white-space: pre;
}


li::marker {
font-size: 10px;
color: grey;
}
<ol><li>lorem ipsum
<li>&gt;&gt; lorem ipsum
<li>lorem ipsum,\
<li>lorem ipsum.
<li>&gt;&gt; lorem ipsum
<li>lorem ipsum
<li>lorem ipsum
<li>lorem
<li>ipsum
<li>&gt;&gt; lorem ipsum
<li>lorem ipsum
</ol> 

然而,::marker样式似乎有限(list-style-type)。例如,删除周期或 vertical-align: super似乎需要其他变通方法(回到 li:beforecounter)。