Code block line numbers

Overview

With Hugo, when you include code samples in your Markdown, you have three options in relation to line numbers:

  1. Do not display line numbers (default)
  2. Display line numbers inline
  3. Display line numbers in a table cell

The functional difference between the last two is subtle—a trade-off between two third-party software defects.

  • When displaying line numbers inline, and a Firefox user copies and pastes your code, there will be a blank line between each line of code due to a Firefox bug reported in 2016. This behavior is unlikely to change.
  • When displaying line numbers in a table cell, and you highlight one or more lines with the hL_lines highlighting option, the height of the number in the highlighted line will be slightly different than the rest of the line. This is due to a bug in the Chroma syntax highlighter.

Set the default behavior in your site configuration:

[markup.highlight]
lineNos = false   # false (default), inline, or table

Override the default behavior as needed by setting the lineNos highlighting option when using a fenced code block or the highlight shortcode:

```python {lineNos=inline}
a, b = 3, 4
print(a, b)
```

{{< highlight python "lineNos=inline" >}}
a, b = 3, 4
print(a, b)
{{< /highlight >}}

The problem

The rendered appearance of your code samples will vary depending on which of the three options you choose. This example (a screen capture) uses the rrt syntax highlighting style.

default appearance

Notice the variations in padding and the problem with overflow.

The solution

Add these CSS rules to your style sheet to target each of the three variations:

assets/css/code-blocks.css
/* Code blocks */
/* ------------------------------------------------------------------------- */

/* Applies when there are no line numbers, or when line numbers are inline. */
.highlight > pre {
  padding: 1em 0 1em 1em;
}

/* Applies when line numbers are in a table cell. */
.highlight div {
  padding: 0 0 0 1em;
}

/* Applies to all. */
.highlight div,
.highlight > pre {
  overflow-x: auto;
  /* add optional border-radius and box-shadow here */
}

/* https://github.com/alecthomas/chroma/issues/722
   First cell (line numbers): fixes the row-height mismatch by giving each
   row its own flex box, matching the flex box chroma already puts on each
   .line in the second cell. Only applies with lineNumbersInTable = true and
   noClasses = false; chroma doesn't render these classes otherwise. */
.highlight .chroma .lntable .lntd:first-child .lnt,
.highlight .chroma .lntable .lntd:first-child .hl {
  display: flex;
}

/* https://github.com/alecthomas/chroma/issues/722
   Second cell (code): without this, the cell won't consume the remaining
   width, so a long line overflows the page instead of scrolling within the
   code block. Only applies with lineNumbersInTable = true and noClasses =
   false; chroma doesn't render these classes otherwise. */
.highlight .chroma .lntable .lntd + .lntd {
  width: 100%;
}

Now we have a consistent appearance and proper overflow handling with a horizontal scroll bar that appears when needed.

normalized appearance

To learn more about the appearance of your code blocks, see the article about syntax highlighting styles.

Last modified: