I’ve been looking into Tufte CSS recently. Tufte CSS -inspired by the teachings of the legendary Edward Tufte1- provides suggestions and tools to style web articles for improved legibility.

I’ve started to incorporate some of those principles here while still trying to keep the authenticity of my original design. Most of these changes have been in the realm of CSS however the sidenotes feature was a slightly trickier beast.

I’ve implemented this feature in my blog theme “Henry” for both Hugo & Jekyll.

Jekyll kramdown comes built in with a footnotes feature that I’ve used here for some time. It works pretty well for the most part. The only problem though is -as the names suggests- it displays the notes all the way at the bottom of the articles near the footer.

Edward Tufte instead suggests the use of “sidenotes”:

Sidenotes are like footnotes, except they don’t force the reader to jump their eye to the bottom of the page, but instead display off to the side in the margin.

So my objective was to use the existing kramdown pipes and generate the footnotes, but display them off to the side in the margin instead of at the bottom.

Pulling this off is tricky with pure CSS but is baby talk for javascript. So I pulled out my trusty old jQuery2 chops and got this fun side project done.

You can find the js source code here.

As is the case with these things though, the devil is in the details. I got the basic functionality down in about an hour but adding the finishing touches took more testing and improving. Here’s some of the ones I had to tackle:

Image loading throws the position off:

Since jQuery loads eagerly, it typically wouldn’t wait for the images to load before calculating the position. This would cause the position to be off sometimes.

This is a one-line fix in jQuery:

$(window).on("load", function() {
    // executes after everything in the DOM loads
}

Resizing the browser throws position off:

Since most folks read blog posts on their phones and tablets these days, there’s a much smaller chance they’re resizing their browser. But if you’re on a laptop (as I am most of the time) then resizing your browser will completely throw the positioning off again.

While there might exist more optimum solutions to fix this, I went with the simpler approach of just detecting window resize changes and just reading the sidenotes again:

$(window).resize(function() {
    loadSidenotes(ww, $fnli, fncount, $fn);
});

I try to optimize this a little by “caching” the previous size and only reloading the notes again if I detect a difference.

$(window).resize(function() {
    const new_ww = $(".wrapper").outerWidth();
    if (new_ww === ww) return;

    // console.log(" XXX -- RESIZE -- XXX ");

    ww = new_ww;
    $(".sidenote").remove();
    loadSidenotes(ww, $fnli, fncount, $fn);
});

Again, this is probably not the most optimum solution but

  • I don’t imagine people resizing their browser window that often
  • there aren’t that many footnotes per post

So I opted for a simpler more understandable solution (than a performant one) - an important software engineering learning that hasn’t failed me so far.

I also realized that my responsive CSS needed some tweaks, so had to tighten that up too.

Remove footnotes from the bottom

If the sidenotes land up displaying successfully, then I actually go the extra mile and remove the footnotes from the bottom of the post. While I don’t have to do this, I think removing cruft and keeping it clean with just the essential content helps the reader know when they’re done.

On hover highlight the sidenote

By default I didn’t want the sidenote to really jump out and distract from the post content. So by default they show up in a slightly muted color. But if you highlight the super script link 3, it should brighten the sidenote.

Optimize for mobile sizes

Now this is great for larger displays like tablets and laptops, but for smaller displays like most mobile phones, the whole sidenote thing doesn’t work as well. So in these cases, I only show the border marker indicating that a sidenote exists. I also don’t mute the color as the border is less distracting.

In addition, I keep the original treatment and clicking the link takes you to the bottom (as before). A future optimization would be to go all Tufte on this and displaying the sidenote on clicking. This should be easy enough to implement with jQuery.

This was a fun side project but sweating the details takes more time than you would otherwise assume. What do you think? Would love to hear your thoughts or suggestions on making this better.


  1. noted for his writings on information design and as a pioneer in the field of data visualization ↩︎

  2. Yes, I know jQuery is old school and the youngins probably use fancier alternatives today but I love me some jQuery and it gets the job done. ↩︎

  3. If you’re still reading this, thank you. As a sign of gratitude this is a dummy sidenote to make it easier for you to test my sidenote display. ↩︎