Provide Line Numbers for Your Code Listings

Have you ever wanted to list your code on a website and automatically number each line? Sure, you can do it manually, but it’s painful to go back and re-number all those lines should you decide to change the code. Also, it’s difficult for your viewers to copy and paste your code without having to back out all those line numbers.

Well, you’ll be glad to know that it’s really easy to implement this automatic line numbering feature. All you need to do is encase your code in <pre> … </pre> tags, and then let JavaScript and CSS do its stuff!

In the example below, we use jQuery, but you can use plain old JavaScript. All you really need to do is find a way to select the code between the <pre> … </pre> tags, and you’re good to go.

First, the special CSS sauce. We’ll make use of the CSS properties counter-reset, counter-increment and :before. You might have guessed, but we’re going to reset a line counter, then increment it with each line, and then insert the line number before each line.

The entire CSS file appears below. Note that we assume your <pre> tags have a “test” class associated with them.

pre.test {
      counter-reset: linecounter;
}

pre.test span.line{
      counter-increment: linecounter;
}

pre.test span.line:before{
      color: #a0a0a0;
      text-align: right;
      content: counter(linecounter);
      width: 3em;
      display: inline-block;
      border-right: 1px solid #a0a0a0;
      margin-right: 5px;
      padding-right: 2px;
}

Okay, so you might have seen that each line within the <pre> … </pre> tags need to be encapsulated with the <span class=”line”> tag. It is important that each line have this encapsulation so that we can identify it as a new code line, and we can pre-pend it with the :before tag. I’ll get to this in a moment, but first notice how we not only pre-pend each line with a number, but we provide a width to the number field and put in a border to the right. This helps your readers separate the line numbers from the code. Also, in this particular case, the line numbers and the border take on a lighter shade than the rest of the text on the line. Again, this allows your readers to logically separate the line numbers from the code.

So how do we pre-pend each line with a <span> tag? JavaScript, of course! Below is some simple jQuery code that does the following:

  1. Get a reference to the whole <pre class=”test”> tag.
  2. Split that reference on hard line-returns. If you’re using an MSDOS text file, you may have to first replace all occurrences of \n\r with \n.
  3. Create an empty output string. This output string will be loaded with all the text within the <pre> tags, but with each line pre-pended.
  4. Cycle through each entry in the split array (from step 2) and recreate the line with the <span> tag encapsulation. Make sure to append the proper line return sequence (either \n or \n\r) as appropriate for your operating system.
  5. Add each of the lines from the previous step into the empty string you created in step 3, slowly building up the new <pre> text lines with modified ones.
  6. When all lines have been added, replace all the HTML within the <pre> … </pre> sections with the new string.

Here’s the jQuery / JavaScript code:

$(function() {
    var test = $('pre.test');
    var temp = test.html().split('\n');
    var insert = "";

    $.each(temp, function() {
        insert += '<span class="line">' + this + '</span>\n';
    });

    test.html(insert);

});

Once you load your raw code into your HTML document, JavaScript will have a go at it and change all the <pre> … </pre> lines, and then CSS will have a go at it to pre-pend all the line numbers. The cool thing is that when people try to copy and paste, the line numbers will not end up in their results!

Best,
Dan

PS: You might wonder why I haven’t numbered the lines of code above. Well, for the time being, I find it easy to implement line numbering when I have complete and unfettered access to the JavaScript and CSS files; however, I’m currently using WordPress for this site, and I’ve not yet figured out how to get all this special JavaScript and CSS code to work within it. (I made a couple attempts, but the results were too embarrassing to show!)