CSS-only line numbers

I am trying to create pre box code with line numbers before each line. I prefer to do this only with CSS. This is what I did

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> 

However, all lines are numbered 1. The increment does not work. Here is jsfiddle

  • What am I doing wrong?
  • What is browser compatibility with this CSS only solution?
+53
html css css-counter
Nov 28 '16 at 10:41
source share
3 answers

Why does the counter not increase?

You do not reset or create a counter at the parent tag level. If you add the following line to the pre selector, the code will work fine. When you do not create a counter (using counter-reset ) at the parent level, each element will create its own counter, and then increment it.

 counter-reset: line; 



When is the counter created?

From the W3C Specs :

The counter-reset property creates new counters for an element.

Counter and counter-increment properties control the value of existing counters. They only create new counters if the element does not yet have a counter of the specified name .

In this case, what happens is that we did not create a counter using the counter-reset property, and therefore the counter-increment property in the span:before pseudo-element selector would create a counter for the name and increment This.




How does the counter know the current value?

Again from W3C Specs :

If the element has a previous sibling, it must inherit all siblings counters . Otherwise, if the element has a parent element, it must inherit all the parent counts . Otherwise, the element must have an empty set of counters.

The element then inherits the counter values ​​from the immediately preceding element in document order .

Here, since the counter is created only in the pseudo-element, its parent ( span ) does not know about its creation, and therefore the brothers and sisters of this span do not inherit the counter. Since it does not even inherit any counter, it also does not get the current value from the previous element.




Why is a counter created on the parent computer?

When a counter is created at the level of the pre tag, the counter is then passed to each of its children (that is, each span and, in turn, each span:before will know or inherit this counter), and now increment statements in span:before will only increment the counter value that it received from the parent.

Now, since each span inherits the line counter from its previous brother, they also inherit the current value from the previous element in the document order and, therefore, it continues to grow from 1 to 2, 3, etc.




Why use a range increment counter or a pre-run counter?

As you might have guessed, the counter-increment property creates a new counter when there is no existing counter, and so adding counter-increment: line to the span will create a counter on the first interval that occurs. Now, since every span sibling inherits this counter, it does not create a new one each time and rather just inherits the value from the previous element. Thus, this approach will work, but it is always better to create a counter explicitly using the counter-reset statement.




How is the browser supported?

Browser support for CSS counters is incredibly good. This is not a new thing in CSS, and support is available even in IE8 .




Demo:

 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> 
+66
Nov 28 '16 at 10:43
source share

You need to increase line in your range:

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

Take a look at this updated jsfiddle .

+1
Nov 28 '16 at 10:44
source share

Hi, you need to reset the counter on the previous / above downloaded item, check https://jsfiddle.net/n2xkgt7s/2/ pre { counter-reset: line; } pre { counter-reset: line; }

0
Nov 28 '16 at 10:49
source share



All Articles