How to add line numbers to pre tags

Author: Bjørnar Hagen

Date published: 2021-05-06T14:25:01Z

How to add line numbers to pre tags

Photo by <a href="https://unsplash.com/@adigold1">Adi Goldstein</a>

Reading code is easier when you have line numbers, but how can you show line numbers in a <pre> tag? This can easily be solved with a few lines of JS and CSS, no need for a big external library.

JS:

 1function addLineNumbersToPres() {
 2  const pres = document.querySelectorAll('pre')
 3  pres.forEach((pre) => {
 4    const lineNumberWrapper = document.createElement('span')
 5    lineNumberWrapper.classList.add('pre-line-numbers')
 6
 7    const preLines = pre.textContent.split('\\n').length
 8    for (let i = 0; i < preLines - 1; i++) {
 9      const span = document.createElement('span')
10      span.appendChild(document.createTextNode(i))
11      lineNumberWrapper.appendChild(span)
12    }
13
14    pre.insertBefore(lineNumberWrapper, pre.firstChild)
15  })
16}

This changes the HTML for the <pre> tag to look something like this:

 1<pre>
 2  <span class="pre-line-numbers">
 3    <span>0</span>
 4    <span>1</span>
 5    <span>2</span>
 6    <span>3</span>
 7    <span>4</span>
 8    <span>5</span>
 9  </span>
10  <code>
11    // Code comes here
12  </code>
13<pre>

Now for the styling.

CSS:

 1pre {
 2  position: relative;
 3  width: 100%;
 4  overflow: auto;
 5  display: grid;
 6  grid-template-columns: min-content max-content;
 7}
 8
 9pre .pre-line-numbers {
10  display: flex;
11  flex-direction: column;
12  height: 100%;
13  text-align: right;
14  user-select: none;
15}

Extra: According to caniuse.com user-select without prefixes is only supported by 50-70% of browsers at the time of writing, so here’s the prefixed properties if you want to add them:

1pre .pre-line-numbers {
2  -webkit-user-select: none;
3  -khtml-user-select: none;
4  -moz-user-select: none;
5  -ms-user-select: none;
6}

What about syntax highlighting?

Syntax highlighting is much more complicated to solve, but maybe I’ll make a post about it one day. For now my <pre> tags remain black and white.

Update: I’ve added syntax highlighting to my page, it’s setup via Hugo.