Author: Bjørnar Hagen
Date published: 2021-05-06T14:25:01Z
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.