Filling The Cracks

The latest posted version of SyntaxHighlighter is here. For the change history, or to download older versions from this site, see the downloads page.
Mind The Gap!

SyntaxHighlighter can display line numbers on the left side of the code block, in an area called the gutter. As a result of other changes that I’d made, the gutter sometimes showed gaps between the line number elements. I added some JavaScript to resize the number elements so that they’d be contiguous, closing any gaps. However, that code needs the offsetHeight for each line in the code block. As I then discovered, when JavaScript so much as reads the offsetHeight of an element, it’s likely that the browser will need to reflow the page to calculate the value. Repeat that for enough lines, and you’ve got a bit of a performance issue (or I do, depending on how you look at it.)

At one point, I’d thought that I could bypass the height adjustment for the most common cases (e.g., text lines that are short enough not to wrap.) But life and HTML come with few guarantees; testing showed that some browsers, in some environments, would still produce some 1-pixel gaps like so:

Gutter, on the left, showing unwanted white lines.

Gutter, left, showing unwanted white lines. (The text on the right is blurred; do not adjust your eyes.)

(The gaps appeared below lines that had keywords highlighted in boldface fonts. Depending on the fonts that the browser is using, the boldface can sometimes add a pixel to the height of the text line.)

Sometimes the best way to solve a problem is to make it no longer be a problem. I’d caused the gaps to appear by changing how backgrounds are rendered. In the original SyntaxHighlighter, the number elements are transparent; the gutter’s background is the background of the top-level <div> for the entire code block. There may be gaps between the number elements, but those gaps can’t be seen. I couldn’t easily go back to that approach, but thinking about it inspired a new one: By stretching the first gutter element vertically, it could be used to provide the background for the gutter. The remaining gutter elements would then be laid out over that first one. Here’s an illustration:

The first number element fills the gutter vertically; the remaining elements are placed on top of it, leaving no visible gaps.

The first number element fills the gutter vertically; the remaining elements are placed on top of it, leaving no visible gaps.

The gaps are invisible once more. The associated JavaScript still causes some reflow, but no more than five times per code block, a much smaller overhead in most cases.

, , ,

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>