Create Line Numbers on Pre with CSS Only

Create line numbers on pre with CSS only

Why does the the counter not increment?

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

counter-reset: line;

When does a counter get created?

From the W3C Specs:

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

The counter-set and counter-increment properties manipulate the value of existing counters. They only create new counters if there is no counter of the given name on the element yet.

In this case what happens is that we haven't created a counter by using the counter-reset property and so the counter-increment property in the span:before pseudo-element selector would create a counter of the given name and increment it.


How does the counter get to know the current value?

Again from the W3C Specs:

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

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

Here since the counter is only created in the pseudo-element, its parent (the span) is not aware of its creation and so the siblings of this span doesn't inherit the counter. Since it doesn't even inherit any counter, it doesn't get the current value from the preceding element either.


Why does creating the counter on parent work?

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

Now since each span inherits the line counter from its previous sibling, they will also inherit current value from the preceding element in the document order and thus it keeps going up from 1 to 2, 3 etc.


Why does using counter-increment on span or pre work?

As you've guessed, the counter-increment property creates a new counter when there is no existing counter and so adding counter-increment: line on the span will create a counter on the first span that is encountered. Now, since each sibling of the span inherits this counter, it doesn't create a new one every time and rather just inherits the value from the preceding element. Thus this approach will work but it is always better to create the counter explicitly using a counter-reset statement.


How is the browser support?

Browser support for CSS counters is unbelievably good. It is not a new thing in CSS and support for it 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>>> 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>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
<span>lorem ipsum</span>
</pre>

How to make code editor-like line numbers using solely CSS?

UPDATE: Just tested on Firefox, different layout so the snippet below does not number the lines. (FF just puts in <br> rather than any further HTML structure).

Will leave this answer up for a bit in case it helps someone get to a general answer for all common browsers.

ORIGINAL ANSWER:
At least on Edge/Chrome the extra lines seem to be encased in div elements.

This snippet numbers the first line, which is just a span, in the same way that you have done but then numbers using the counter called line on the div immediate children of the pre rather than on the encased spans.

pre {
background: #303030;
color: #f1f1f1;
padding: 10px 16px;
border-radius: 2px;
-moz-box-shadow: inset 0 0 10px #000;
box-shadow: inset 0 0 10px #000;
counter-reset: line 1;
}

pre>span::before {
content: '1';
display: inline-block;
padding: 0 .5em;
margin-right: .5em;
color: #888;
}

pre div {
line-height: 1.5rem;
counter-increment: line;
}

pre div::before {
content: counter(line);
display: inline-block;
padding: 0 .5em;
margin-right: .5em;
color: #888;
}
<pre contenteditable="true" spellcheck="false">
<span>lorem ipsum</span>
</pre>

Align code line numbers with CSS

If you want a pure CSS solution, there is only one way: use a fixed-width solution, i.e. explicitly declare a width on the ::before pseudo-element. However, this approach is never future-proof as you will have to account for scenarios where the counter might run into 3, 4, or more digits.

pre {  counter-reset: line;}
code { counter-increment: line;}
code::before { content: counter(line); display: inline-block; width: 1.5em; /* Fixed width */ border-right: 1px solid #ddd; padding: 0 .5em; margin-right: .5em; color: #888; -webkit-user-select: none;}
<pre><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code><code>Code</code></pre>

html: How to add line numbers to a source code block

While technically my question is already answered by Rounin (thanks), truth is I was not fully satisfied with the result, because I didn't state a couple other requisites that I felt were important after posting the question, and they fail with that solution:


  1. When a line wraps around, it should go underneath the above line, not underneath the line numbers.
  2. Both the numbers and the text columns should be style-able (notably, the background of the whole column should be easily changeable).

I tried a solution with another inline-block, but it failed #5, and had problems with adjusting to any width.

<OL> was quite close, but not quite there. An alternative to <OL> that I knew wouldn't fly was to use a table. It wouldn't fly, because the browser needs a <PRE> element in order to copy/paste spaces and tabs properly.

Then all of a sudden, a solution clicked in my head. Forcing an element that is not a table to behave as if it was a table, is the exact purpose of the table-xxxx display values!

So here we go. Tested in Iceweasel 24.7.0 and Chromium 35.0.1916.153. The demo includes extra styling as an example of the versatility of the method.

The CSS:

/* Bare bones style for the desired effect */
pre.code {
display: table;
table-layout: fixed;
width: 100%; /* anything but auto, otherwise fixed layout not guaranteed */
white-space: pre-wrap;
}
pre.code::before {
counter-reset: linenum;
}
pre.code span.tr {
display: table-row;
counter-increment: linenum;
}
pre.code span.th { /* used for line numbers */
display: table-cell;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
pre.code span.th::before {
content: counter(linenum);
text-align: right;
display: block;
}
pre.code span.th {
width: 4em; /* or whatever the desired width of the numbers column is */
}
pre.code code {
display: table-cell;
}

And the HTML:

<pre class="code">
<span class="tr first-row"><span class="th"></span><code> indented line</code></span>
<span class="tr"><span class="th"></span><code>unindented line</code></span>
<span class="tr"><span class="th"></span><code> line starting and ending with tab </code></span>
<span class="tr"><span class="th"></span><code></code></span>
<span class="tr"><span class="th"></span><code>the above line should be empty</code></span>
<span class="tr"><span class="th"></span><code>overlong line that wraps around or so I hope because it's really long and should overflow the right sided margin of the web page in your browser</code></span>
<span class="tr"><span class="th"></span><code>fill up to ten</code></span>
<span class="tr"><span class="th"></span><code>lines to check</code></span>
<span class="tr"><span class="th"></span><code>alignment</code></span>
<span class="tr"><span class="th"></span><code>of numbers</code></span>
</pre>

Demo with extra styling

Update: Since I posted the question, learned that the GeSHi syntax highlighter has an option to use the following schema, which also meets all requisites and may be more acceptable to those that are allergic to tables:

<ol>
<li><pre>code</pre></li>
<li><pre>code</pre></li>
<li><pre>...</pre></li>
</ol>

show linenumber on code blocks using only css

I personally would have structured the line numbers differently in the HTML, but keeping with what you have now;

One thing you could do is change the line-height on .markdown-body pre code to 0; Then on .line-numbers-rows > span:before set your line-height to 19px;

Updated code:

.markdown-body hr:after,.markdown-body hr:before {    content: "";    display: table;}.markdown-body .anchor:focus,.markdown-body a:active,.markdown-body a:hover {    outline: 0;}@font-face {    font-family: octicons-anchor;}.readme {    border: 1px solid #ddd;    border-radius: 3px;    display: table;    margin: 20px auto;    padding: 30px;    width: 790px;}
.markdown-body code,.markdown-body pre { font: 15px Consolas, "Liberation Mono", Menlo, Courier, monospace;}
.markdown-body pre > code { background: 0 0; border: 0; font-size: 100%; margin: 0; padding: 0; white-space: pre; word-break: normal;}.markdown-body .highlight { color: #5e6e5e;}.markdown-body .highlight pre,.markdown-body pre { background-color: #fbebd4; border-radius: 3px; font-size: 85%; line-height: 1.45; overflow: auto; padding: 16px 30px;}
.markdown-body pre code { background-color: transparent; line-height: 0;}.markdown-body pre code:after,.markdown-body pre code:before { content: normal;}
pre.line-numbers { position: relative; line-height: 0; width: em(440); margin: 4em auto; padding: 0.5em; border-radius: 0.25em; counter-reset: linenumber;}
pre.line-numbers > code { position: relative; white-space: inherit;}
.line-numbers .line-numbers-rows { position: absolute; top: 0; left: -4.5em; width: 4em; letter-spacing: -1px;
pointer-events: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;}
.line-numbers-rows > span { pointer-events: none; display: block; counter-increment: linenumber;}
.line-numbers-rows > span:before { content: counter(linenumber); color: #999; display: block; border-right: 1px solid #ddd; padding-right: 0.8em; text-align: right; line-height: 19px;}
<div class="readme">    <article class="markdown-body">        <h1>File <code>doc.my</code></h1>        </br><h3 id="requestmain">    RequestMain</h3>        <p>RequestMain class. It is the user/client code.</p>        <div class="highlight highlight-source-swift">            <pre class="line-numbers"><code class=" language-js"><span class="pl-k">class</span> <span class="pl-en">RequestMain</span> {  <span class="pl-k">static</span> fn <span class="pl-c1">main</span>() {    request <span class="pl-k">=</span> new <span class="pl-c1">Request</span>()    request.<span class="pl-smi">FirstName</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>Haifeng123456789<span class="pl-pds">"</span></span>    request.<span class="pl-smi">LastName</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>Huang     <span class="pl-pds">"</span></span>    request.<span class="pl-smi">Dept</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>Department of Labors<span class="pl-pds">"</span></span>    RequestHandler.<span class="pl-c1">handle</span>(request)  }}<span class="line-numbers-rows">      <span></span>      <span></span>      <span></span>      <span></span>      <span></span>      <span></span>      <span></span>      <span></span>      <span></span>    </span>  </code></pre>        </div>

Add Line Number to existing HTML

By inspiring from this question, I have developed a solution for your question. You can use the counter-reset and counter-increment property to achieve this

<html>
<head>
<style>
.container {
counter-reset: line;
}
.container .lineNum {
display: block;
line-height: 1.5rem;
}

.container .lineNum:before {
counter-increment: line;
content: counter(line);
display: inline-block;
margin-right: .5em;
}
</style>
</head>
<body>
<div class="container">
<div id="1" class="lineNum"><right><span>line 1</span></right></div>
<div id="2" class="lineNum"><right><span>line 2</span></right></div>
<div id="3" class="lineNum"><right><span>line 3</span></right></div>
</div>
</body>

</html>

How can I generate line number from css or javascript based on height of container

Here's something: (written fast, feel free to adjust CSS etc)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<style>
#code {
line-height: 15px;
}
.holder {
display: flex
}

</style>
</head>
<body>

<div class="holder">
<div>
<pre id="lines">
</pre>
</div>
<div>
<pre id="code">
.aaa {
bbb
}
.ccc {
ddd
}
</pre>
</div>
</div>

</body>
<script>
const codeHeight = document.getElementById('code').offsetHeight;
const lines = Math.ceil(codeHeight / 15);
let html = '';
for (i = 1; i < lines; i++) {
html += i + '<br>'
}
document.getElementById('lines').innerHTML = html;
</script>
</html>

Here's the JS fiddle: https://jsfiddle.net/4aowc26f/

Number 15 in calculation is due to 15px line height. Feel free to introduce variable for this one.

How can I add line numbering to my paragraph?

You can create custom counter and use counter-increment: custom-counter+5 so it will increment by 5 but it will start from 5 not from 1, but you can add number 1 for first p with :before and exclude it from counter.

.content {  width: 200px;  counter-reset: custom-counter;}p {  display: table;}p:not(:first-child):before {  counter-increment: custom-counter+5;  content: counter(custom-counter)". ";  display: table-cell;  color: #aaa;}p:first-child:before {  display: table-cell;  color: #aaa;  content: '1. '}
<div class="content">  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium, blanditiis.</p>  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Non, eligendi.</p>  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis, minus.</p>  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque, repellendus?</p>  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Exercitationem, laboriosam.</p></div>


Related Topics



Leave a reply



Submit