About The Footnotes…

By Shamus Posted Tuesday Nov 2, 2021

Filed under: Random 55 comments

I recently got an email asking about the footnotes I use on this site. These sorts of questions pop up pretty often. People ask things like: Is there a plugin I can use? Did you come up with the idea yourself? How do you create them? The answers to which are No, No, and “It’s complicated”.

As many have suspected, I stole the idea for the footnotes from the XKCD “What-if?” series. I don’t remember when I first started using them. I just did a quick scan through the archives and found a footnote in a post from 2014, but I’m not sure how much further back they might go.

Over the years I’ve become so used to footnotes that I find it annoying to write without them. If I find myself writing a long email, I’ll usually end up with lots of awkward parenthetical statements that I wish I could turn into footnotes.

Before I had footnotes, I sometimes wrote nested parenthetical statements. They were fun to write, but they’re ugly as hell and very hard on readability.

There weren’t any footnote plugins available back when I first introduced this feature. I cobbled it together myself by stealing some javascript from the What-if page and making my own version. To get a footnote system working in WordPress you need to do what most modern web developers do and string a bunch of different systems and languages together into a big Rube Goldberg machine.

First is the syntax. You don’t want to clutter up your articles with tons of complex HTML. So I use a fairly minimalist shortcode that looks like this:

Here is an example sentence.[ref|And here is an example footnote.]

Is that great syntax? Eh. Probably not. But it’s what I came up with, and so we’re stuck with it now. So you put the above text into an article. Then you create a WordPress filter in PHP that will find these tags and turn them into useful HTML.

function roller_tag_ref ($text)
{
  global  $reftagnum;
  global  $reftagpost;
  global  $reffootnote;
 
  $reftagnum = 1;
  if ($reftagpost != get_the_ID()) {
    $reftagpost = get_the_ID();
    $reftagnum = 1;
  }
  while (1) {
    $tag_start = strpos ($text, "[ref");
    if ($tag_start === FALSE)
        return $text;
    $tag_end = strpos ($text, "]", $tag_start);
    if ($tag_end === FALSE)
        return $text;
    $tag_length = $tag_end - $tag_start;
    $find = substr ($text, $tag_start, $tag_length + 1);
    $tag = substr ($find, 4, $tag_length - 4);
    $info = explode ("|", $tag);
    $reftag = 'INVALID';
    if (count ($info) >= 3) {
      $reftag = $info[1];
      $refbody = $info[2];
    } else if (count ($info) >= 2) {
      $reftag = $reftagnum++;
      $refbody = $info[1];
    } else
      return $text;
    $reftitle = $refbody;
    if (is_feed ())
      $replace = "<sup>[$reftag]</sup>";
    else
      $replace = "<span class='snote' title='$reftag'>$reftitle</span>";
    $reffootnote .= "<p>[$reftag] $reftitle</p>";
    $text = str_replace ($find, $replace, $text);
  }
}

That code will take the original sentence and expand it to this:

Here is an example sentence.<span class='snote' title='1'>And here is an example footnote.</span>

The footnote text is shoved inside of a named span tag so that we can hide or show it whenever we like. Now, maybe you’re thinking, “Hey Shamus. This HTML doesn’t look that much longer than the shortcode you use above. Is this really necessary?”

Yes, it is. The code also handles the automatic numbering. I don’t want to have to re-number all of my footnotes because I decided to add a new one at the top of the article.

Now we need to use CSS to control its appearance…

.snote_tip
{
  font-size:          smaller;
  display:            inline-block;
  visibility:         hidden;
  position:           absolute;
  overflow:           hidden;
  padding:            0.5em;
  overflow:           auto;
  background:         #fea;
  color:              #000000;
  border:             2px solid #874;
  box-shadow:         0.25em 0.25em 0.25em #555;
  z-index:            1;
  max-width:          50%;
}
 
.snote_tip:hover {  cursor: pointer; }

We make the font smaller, we make sure the box doesn’t take up any space in the document, and we do some obvious style stuff like coloring things and adding a drop shadow. Also, we make sure the boxes are hidden by default.

Fine. But now comes the hard part. We need to reveal a box when the user clicks on the number. And for that we need some Javascript. I don’t know why, but the JS I stole from What-if managed to break after a couple of years. Then a reader sent me this to replace it:

//call this function once the page has loaded
window.addEventListener('load', snote_init, false);
window.addEventListener('mouseup', snote_hide, true);
 
//this function will add a span with snote_tip class where a span with the snote class is used, 
//this reduces the html needed and makes writing notes so much simpler/cleaner.
function snote_init() {
    var snote_elements = document.getElementsByClassName('snote');
    for (var i = 0; i < snote_elements.length; i += 1) {
      (function(i)  {
        var snote_element = snote_elements[i];
 
        snote_element.innerHTML = '<span class="snote_refnum" title="">[' + snote_element.title + ']
        </span>' + '<span class="snote_tip" id="snote_' + i + '">' + snote_element.innerHTML + '</span>';
        snote_element.style.display = 'inline-block';
        snote_element.addEventListener ("mouseup", function () {snote_show(i)}, false);
      })(i);
   }
}
 
function snote_hide (arg)
{
  var snote_elements = document.getElementsByClassName('snote_tip');
  for (var i = 0; i < snote_elements.length; i += 1) {
    var snote_element = snote_elements[i];
    snote_element.style.visibility = 'hidden';
  }
}
 
function snote_show(arg)
{
    var snote_tip = document.getElementById('snote_' + arg);
 
    if (snote_tip.style.visibility == 'visible')  {
      snote_tip.style.visibility = 'hidden';
    } else {
      snote_tip.style.visibility = 'visible';
    }
}

And now the system works:

Here is an example sentence.And here is an example footnote.

So this system is a Frankenstein’s monster of HTML, custom shortcode, PHP, CSS, and Javascript.

It’s not perfect. The size and positioning of the text box is left to the browser to decide. That means that if a footnote lands near the right margin, the box might appear slightly off-screen.This is really only a problem in mobile view, where the text goes right to the edge of the screen. On a desktop, we have decadently large margins that can accommodate footnote boxes that spill out of the main reading area.

But wait! Before you copy & paste my horrible system to use on your own site, you should probably try this plugin. The shortcode isn’t as shortIt uses opening and closing tags, which makes it more verbose AND it means you can have problems with mismatched tags. but it’s probably ten times easier than rolling your own. I’d use it myself if I didn’t have several years of legacy text tying me to my current system.

There, I managed to write 1,000 words about web development and I managed to resist the urge to complain about the awfulness of PHP / Javascript. You’re welcome.

 

Footnotes:

[1] And here is an example footnote.

[2] This is really only a problem in mobile view, where the text goes right to the edge of the screen. On a desktop, we have decadently large margins that can accommodate footnote boxes that spill out of the main reading area.

[3] It uses opening and closing tags, which makes it more verbose AND it means you can have problems with mismatched tags.



From The Archives:
 

55 thoughts on “About The Footnotes…

  1. Erik says:

    There, I managed to write 1,000 words about web development and I managed to resist the urge to complain about the awfulness of PHP / Javascript. You’re welcome.

    So close, Shamus.. so close.

    1. Chris says:

      Yeah complaining about the awfulness of PHP and JavaScript is what gets some of us out of bed in the morning. And it’s not like not complaining somehow makes them less awful. They’ve earned the opprobrium.

  2. Thomas says:

    The footnote about footnotes appearing slightly offscreen appeared slightly offscreen for me. I appreciate that

  3. Destrustor says:

    In my very particular case, the footnotes occasionally have a different problem.
    I never full-screen my browser, instead keeping it in a rather limited window that leaves almost no space for any amount of margin. This sometimes causes the footnote to appear as an ultra-tall column of single words (sometimes even half-words) when it gets smushed against the sides of the browser window.

    1. Parkhorse says:

      Same here. Right now I’m reading on a 1080p laptop screen, with this site on one half of the screen (Netflix on the other half). Footnote #3 is a tall column of words, with parts of some words cut off past the right end of the window. Opening a footnote that’s too wide for the current window also doesn’t prompt the browser to provide a horizontal scroll bar.

      Not a big annoyance, easily fixed (just maximize the window briefly), and I’ve always felt it’s a “me” problem.

    2. Yerushalmi says:

      Same here! You have to play with the margin a bit so the footnote ends up on the left side of the screen.

      1. evileeyore says:

        Like so:

        https://i.imgur.com/sP8sh8e.png

        Yes, I had to make my browser window smaller, but I’ve had some in the past that were so stupidly larger and crowded on the border so tightly that I’ve had them spill pretty far down the page… used to be worse but the more generous sidebars we’ve had for a while I have noticed this being a problem for me for a few years (I do have a “smaller” screen compared to Jones these days).

  4. Asdasd says:

    Having had but a tiny glimpse of the awfulness of PHP and JavaScript makes me lament for the sheer number of people who have to toil in this booming section of the industry.

    1. Retsam says:

      It’s worth noting that this isn’t anything like how JS code is largely written today, this is a quite old-style with a lot of rough edges that aren’t necessary nowadays. That whole weird looping construct:


      var snote_elements = document.getElementsByClassName('snote');
      for (var i = 0; i < snote_elements.length; i = 1) {
          (function(i) {
          var snote_element = snote_elements[i];

          snote_element.innerHTML = /*HTML */
          snote_element.style.display = 'inline-block';
          snote_element.addEventListener ("mouseup", function () {snote_show(i)}, false);
          })(i);
      }

      would be written like this, if it were written since about 2015:


      for(const snote_element of document.getElementsByClassName('snote')) {
          snote_element.innerHTML = /*HTML */
          snote_element.style.display = 'inline-block';
          snote_element.addEventListener ("mouseup", () => snote_show(i));
      }

      Yes, the old style is still necessary in cases where IE is supported (which is pretty rare at this point), but even then you rarely *write* it, rather than writing the new version and compiling it down to support old browsers.

      I can’t speak directly to PHP, but I hear it’s improved as much, if not more than JS. You don’t have to lament for us, we’re doing fine, really.

      1. Dev Null says:

        “in cases where IE is supported”

        Not even Microsoft supports IE anymore.

        1. Bubble181 says:

          there are a LOT of internal/intranet/corporate systems that still require IE.
          I work for a big, big company, and I’m still using IE 6, IE8, Edge and Chrome to be able to use/access all the things I need, simply because of compatibility issues.
          I don’t need to tell you this is ridiculous and horrible, but hey.
          I also still work in a Mainframe from the late ’80s and another one from the early ’80s, so…Yeah.

        2. baud says:

          At work we’re at last moving one of the product we’re selling away from IE, even if I think there’s some cases we won’t be porting to Chrome/Edge. But we still have to support clients using older versions and the product still works with IE.

          In our case what tied us to IE was ActivX and java applets.

      2. RFS-81 says:

        Morbid curiosity, but in the old style, why would you need to define an anonymous function that you immediately call and then forget about?

        1. Retsam says:

          It’s a quirk of how “var” worked. Usually variable declarations are “block scoped” – if I do:

          for(let i=0;i<5;i++) { }

          There’s essentially a new copy of i for every iteration of the loop. But var is function scoped, theres basically a single variable shared by all the iterations, it’s more like:

          let i=0;
          while(i<5) {
              i++;
          }

          Most of the time, this is fine… but specifically the case where you’re setting up a callback to run later, this is a problem, because by the time the callback is run, the value of i is no longer what it was during that iteration of the loop. So when show_snote(i) is called, it’s not called with 0, 1, 2…, i is always snote_elements.length.

          The function wrapper fixes it because a function’s argument doesn’t change even if the variable passed to it changes later.

        2. Chad+Miller says:

          I’m pretty sure it’s because of this event handler:

          snote_element.addEventListener (“mouseup”, function () {snote_show(i)}, false);

          It looks like a workaround to prevent all of the EventListeners from being set to snote_show(snote_elements.length -1)

      3. Asdasd says:

        It’s all right, help is on the way. Blink twice if Javascript has your family.

    2. Rick says:

      And if that wasn’t bad enough, people had the idea of using JavaScript for the server side too and now we’ve got the monstrous turd that is Node.

  5. Jin says:

    Can you get it to work on mobile somehow? When I read your blog on my phone, the only way to close a footnote is to click on a different one, leading to a frantic search to find another footnote when they are spaced far apart.

    1. Shamus says:

      On my android phone, I just need to tap anywhere outside of the box to close it. Not sure why that wouldn’t work everywhere.

      Hmmm.

      1. This is due to a longstanding bug in all iOS browsers (since Apple mandate they all use the same rendering engine).

        There was some discussion a few years back about how to fix it in either CSS or JavaScript.

      2. Sardonic says:

        I used to have this problem, but it suddenly went away a couple years ago. I’ve been on iOS this whole time and the footnotes work fine for me, now.

        1. Chad+Miller says:

          I still have it on iOS, but Doctor Professor’s linked post makes a lot of sense given I’ve found that a workaround is to dismiss footnotes by tapping absolutely anything other than the main blog post. Inline images are the most common target.

        2. Jin says:

          Nope, just tried it again, still not working. Although tapping the code snippet just above the footnote does close it. Yes, this is iOS. Pretty please, adopt the fix?

  6. tmtvl says:

    I think it could be possible to make these using but a combination of HTML and CSS (to wit: using check boxes and CSS 3 selectors).

    Basically you’d do something a little like this.

    1. Retsam says:

      These sort of clever “implement dynamic website logic just with HTML/CSS to avoid JS” tricks tend not to be a good idea – they usually are pretty bad for accessibility as they involve non-standard usage of HTML elements and CSS-only tricks that aren’t understandable by things like screen-readers.

  7. Retsam says:

    I’m also rather fond of the concept of footnotes, and tend to use them even in text-only platforms. (I think I’m partly responsible for the common community-style of footnotes like this[1])

    I’m working on spinning up a blog myself – though I’ve theoretically been doing that for years now, I actually have a working prototype this time – and I’m trying to decide how to do footnotes. I really like the what-if style popovers for quick parentheticals, but the “jump to the bottom of the page” style is a lot easier to get working: no issues with positioning or mobile browsers and works out of the box with the many markdown parsers. Plus, bottom of the page footnotes can include code snippets, which is probably a feature I’ll use.

    [1] …though it’s hardly a novel concept, but I don’t see it nearly as much in other communities, and I remember them becoming somewhat more common after a particular forum post in the “This Week I’m Currently Playing” thread where I used a lot of them).

  8. Dave Rolsky says:

    I use Hugo for my blog, and I found a theme with a very similar feature called “jane”. The only difference is that the footnotes are shown on hover, with no need to click.

  9. MrPyro says:

    Typolice:

    The size and positioning of the text box is left to the browser to decide. That means that if a footnote lands near the right magin

    1. Paul Spooner says:

      Also “Then a reader send me this” should probably be “sent”, unless you’re going for caveman dialect, in which case drop the “a”.

      1. BlueHorus says:

        If that happen, comment section fill with correction!

  10. Vertette says:

    I’m pretty sure you should be able to replace this system with a much simpler one using just JS and CSS, but if it works it ain’t stupid.

  11. Philadelphus says:

    class=’snote’

    Snote, brother of Snoke! …Look, it popped into my head and I can’t get it out, so y’all get to share the pain with me now.

    Over the years I’ve become so used to footnotes that I find it annoying to write without them. If I find myself writing a long email, I’ll usually end up with lots of awkward parenthetical statements that I wish I could turn into footnotes.

    Same! Footnotes or parenthetical asides are my mind’s way of dealing with the thousand and one cool tangents and spin-offs of whatever I’m writing, because life of full of fascinating connections that I enjoy finding and sharing. Now guess what two things are severely frowned upon in formal scientific writing? Made writing my thesis this past year a living nightmare, let me tell you.

    1. Syal says:

      Now guess what two things are severely frowned upon in formal scientific writing?

      I’m gonna guess “parables” and “limericks”.

  12. W says:

    Notably this footnote implementation does not work on RSS. I end up either skipping the footnotes entirely or clicking through to find out what one says. I know RSS readers are not a big concern, we lurk in the shadows! But I thought it was worth mentioning.

    I guess a simple title attribute wouldn’t scale up well for longer notes.

  13. Duoae says:

    Before I had footnotes, I sometimes wrote nested parenthetical statements. They were fun to write, but they’re ugly as hell and very hard on readability.

    These sentences resemble me… except that I can’t code so never tried to implement footnotes. Instead I opted for “in situ disruptive quotations”.

    An ugly kludge! :D

  14. The Rocketeer says:

    Missed the chance to put an entire post in a footnote

    1. Retsam says:

      First comment would have been “whole post in footnote, boss”.

      1. Kincajou says:

        It’s the little things that make life worth living!

  15. Misamoto says:

    Now let me sell you on the idea of rewriting the blog in something modern, like React and Typescript…

    Probably not an actually good idea. But here’s a more plausible one: how about open-sourcing it? I might be able to fix the footnotes going off-screen then?

  16. Mark Ayen says:

    It’s probably just the lighting in my office, but the footprints at the top of the article look like they’re sticking up out of he sand, not depressed into it. Weird.

    1. Geebs says:

      I see them as convex unless I remind myself that they must be concave. I initially thought it was some sort of visual gag. My eyes are pretty tired and I can actually feel them straining when I try to “see it right”.

    2. Chad+Miller says:

      I’m seeing it the same way; like someone was buried head-first and this is all we can see of them.

    3. Philadelphus says:

      This happens to me all the time when looking at photos of cratered surfaces on other bodies in the solar system, and it drives me bonkers. Sometimes I can get my brain to realize that that shape is a crater and not a mound; sometimes not.

    4. Syal says:

      I was having no problems, and now I can’t unsee it. You’ve done a terrible thing today.

      1. Mark Ayen says:

        Bwa ha ha.

    5. Chuk says:

      I saw them that way too and even going back and realizing that’s not how sand works, I can’t see it any other way.

    6. pseudonym says:

      This is normal. Since this is a flat photo in 2D there are two ways to interpret the picture. Either convex or concave. Since your brain is used to seeing actual feet it will always render them convex.

      The same thing happens when you make a picture of your face imprinted in clay. It will look like an actual face on a photograph, not like a lump of clay with a face-shaped hole.

      1. Chad+Miller says:

        See also: Necker Cube, Spinning Dancer Illusion…

  17. I’m probably “a reader”.

    In response to Retsam, yes, it’s an “older code”.
    https://www.youtube.com/watch?v=xXTGlvjBejQ

    I forget when this occured (might have been prior to 2015), but even then the code was not new. It was made to slot relatively directly in place of the old one without Shamus needing to redo too much stuff in WordPress. I think there was a slight tweak to it later as well (in regards to how notes display / or doesn’t when the javascript isn’t run).

    And spot on in regards to the weird anonymous function wrapper thing. That is so annoying in javascript.

    As to just using HTML and CSS (no javascript). In modern browsers one can probably do it. And in a way that is how it works currently (it is hidden at first page view and each footnote is unhidden).

    The issue though is the same with or without javascript. Desktop vs Mobile vs TV/Bigscreen layout. If I make my desktop window narrow then the footnotes box changes size, but that’s in latest Chrome for desktop.

    If I recall correctly. footnotes was acting up Shamus went “oh noes, it’s broken”, somebody sent him replacement code that mostly worked and Shamus went “of great, I don’t have to redo stuff, and hardly anything broke, onwards we go”.

    Not having to rely on javascript at all would be nice. But older browsers would have issues with it. And using javascript to “set things up” at page load is not really a sin. Minimizing the need for javascript during the rest of the time thew page is viewed is very important. And in this case it’s user triggered and only temporary.

    I’d love to see a HTML+CSS only solution. Put a demo of it on pastepad or something with a liberal license and if Shamus can “slot it in” without stuff breaking or having to do lots of theme rewriting, awesome for everyone. (using jsbin or jseditor or jsfiddle or something similar)

    I also seem to recall that footnotes was shown again at the end of articles on this site, but that’s no longer a thing?

    For readability and acessability (like a screenreader) having them inline is a huge benefit, but for more traditional “book footnotes” it’s more traditional to have them at the end. Then again we live in a modern world and these kind of inline footnotes are more like asides (which is a specced thing in the living HTML standard).

  18. Richard says:

    Actually, you don’t need any JS at all to make footnotes appear and disappear.

    Assuming the :hover pseudoselector isn’t what you want:

    You can use an invisible checkbox instead – the footnote appears when the checkbox is ticked and vanishes when it isn’t.
    Set the ‘active area’ of the checkbox to be an appropriate region, and there you go.

    <input type=”checkbox” id=”P0″/>
    <label for=”P0″<Click to expand…</label>

    With CSS like:
    input[type=checkbox]:checked label footnote {display: block;} input[type=checkbox]:checked label {display: none;}

    Alternatively, use radio buttons instead to have only one open at a time. Less useful for footnotes but handy for other purposes.

    I had to do this to make a nicely-navigable HTML document that’s usually emailed to someone, which they’ll likely store on their local hard disk for future reference.
    For some reason Chrome refuses to run any JS loaded from the local disk. I’m presume this is for security – I don’t know why and it doesn’t matter – but it meant I had to figure out how to do a lot of stuff in pure CSS.

    1. Rick says:

      Wouldn’t this requires clicking on the note to close it?

      That may break links in the footnotes but also would mean you couldn’t simply click away to close it.

      :focus may help everywhere except iOS.

  19. Rick says:

    Shamus, is there an “add_filter(…” line near your roller_tag_ref() function?

    1. Shamus says:

      I don’t know if it counts as “near”, but yes I have one. All the functions are together, and then the add_filter stuff is at the end of the file. For whatever reason.

  20. And for all of this effort they don’t even work in RSS readers. This means I never get to read any of your footnotes.

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun. Your email address will not be published. Required fields are marked*

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>

Leave a Reply to Kincajou Cancel reply

Your email address will not be published.