The bigfoot.js library is a popular solution to footnotes on the web. I’ve never personally been a fan of it though, because bigfoot.js footnotes are invisible unless you interact with the page. I prefer the visual beautify of small footnotes omnipresent at the bottom of the page, with links that jump you to and from them. It’s a slightly less ideal UX, but it’s a much superior UI.

I’ve noticed two problems that arise with out-of-the-box kramdown footnotes, however:

  1. They always jump you down slightly too far because they jump you to exactly where the text occurs. As a result, you always have to scroll up a little to the context of where you were.
  2. They interfere with your browser history. If an article has a couple of footnotes and you jump down and back up for both of them, that pushes 4 distinct shebangs to your address bar and history. You then have to swipe backwards five times in mobile Safari to get to your previous page. That’s quite cumbersome.

I decided to fix both of these problems with a bit of JavaScript. Here’s what I came up with, using ES6:

$(document).ready(() => {
  /**
   * @param {element} e The element that was clicked
   * @return {element} The element that is being pointed to
   */
  const goTo = (e) => {
    let goTo = $(e.currentTarget).attr('href');
    // remove the pound sign
    goTo = goTo.substr(1);
    // Use document.getElementById() to accomodate colon in element id
    // (https://stackoverflow.com/a/11862160/1591507)
    return $(document.getElementById(goTo));
  };

  /**
   * The amount of top padding when scrolling to/from a footnote
   */
  const padding = 10;

  $('.footnote').click((e) => {
    $(window).scrollTop(goTo(e).offset().top - padding);
    e.preventDefault();
  });

  $('.reversefootnote').click((e) => {
    $(window).scrollTop(goTo(e).parents().offset().top - padding);
    e.preventDefault();
  });
});

This solves both problems mentioned above:

  1. Instead of jumping down too far, you’re always given a padding of 10 pixels. Plus, when jumping back to the text that cites the footnote, you’re sent to the outer element that contains this footnote (hence the parents() call). The resulting parent will usually be a <p> or a <li> tag. This is nice, because it gives you the full context of citation. Only in cases of very long paragraphs of text would this result in the user getting scrolled so high that the footnoted sentence is out of sight.
  2. Instead of allowing the click or touch event to be handled by the browser, JavaScript is intercepting the event and preventing the default behavior, which means no shebangs are pushed to browser history.

Here’s a gist of my JavaScript. I’m using this code here at Drinking Caffeine too, so you can demo the new footnote experience on any article that has footnotes, such as this recent one.