Raphi Rambles

Tooltip Odissey

If asked to name a blogger whose work I've enjoyed, the first one that would pop into my head would the the great (and sadly, late) Shamus Young. If you're into geeky stuff like video games, programming popularization and obsessive nitpicking about storytelling, then I can't recommend this blog enough.

That guy was a huge influence on the way I still think about a lot of stuff, and the itch to start writing myself might not have gotten to me if not for him.

But the funny thing is, I didn't think of him (at least not consciously) when I started building this website. That only came when, catching up on the markdown syntax, I stumbled upon the footnotes feature.

Open the link above and skim a few posts. Look for the citation links1 peperred across the pages and click on one of them.

It's not much, but it's one of the small touches that gave this blog its vibe. And to this day, I always have a thought for the ol' twentysided whenever I see one of those (and also get slightly annoyed when sites stick to the default browser behaviour.2 Maybe it's just a habit I picked up, but I find reading the footnote in place much more convenient).

So since I had way more urgent things to do, I decided to go ahead and spend an afternoon hacking on my own take on the idea.

I haven't looked into his implementation. I might check it out later, but I figured it would be funnier to come up with my own version, especially on a trivial thing like this.

The first thing I realized is that since the footnotes' markup is generated from the article's markdown, I can't easily fool around with it (I guess it's possible, but this is going to require writing a pelican plugin, which is not what I'm interested in at the moment. Also, I'm not sure how straightforward it is to alter only part of the generated output.3 Again, my goal here is just to hack together a small feature, not to become a markdown expert).

So, since I can't directly alter the page's HTML, I guess I'll have to use Javacript.4

Simpler is always better...

My first thought was pretty elementary. Grab all the footnotes gathered at the bottom of the article, clone their children, and add the clones right beside the link that points to them. The actual tooltip hide/show logic shall be handled via CSS.

I got started doing that, and along the way realized that I probably could avoid messing with the DOM by simply extracting the footnote's text and sticking it on the link as an attribute. If CSS could then access this attribute, that would vastly reduce the amount of JS code. I found a codepen online that did just that, pasted it in my template, and lo and behold, it worked!

Here's the script I ended up with:

function SYToolFoot() {
    // Loop over the footnote links
    document.querySelectorAll('a.footnote-ref').forEach(function(footlink) {
        const footnoteId = footlink.href.split('#')[1];
        // Grab the corresponding footnote
        const footnote = document.getElementById(footnoteId);
        // And stick its text in a custom attriibute
        footlink.setAttribute('data-tooltip', footnote.textContent);
    });
}

Now ain't that a beauty!1

Barely 5 lines of js and it looks and feels great. Since the actual showing and hiding is handled via CSS (that's where the real magic happens, and I shamelessly stole that part), I had to trigger it on mouseover instead of requiring a click. But honestly, it feels sleeker that way.

So good job, well done, now let's go grab a beer and reflect on the virtues of simplicity and how much of a better place the world would be if only people would wise up and join us in the perpetual battle against complexity. Right ?

Stock photo. People celebrating in an office.
Stock, sappy corporate pictures as illustrations. Another Shamus hallmark. In fact, I recognized a few photos he used while searching for this one. Source: pexels.com

... Except when it's not.

Hmm. The default behaviour (click & scroll to the bottom) is preserved.5 That's great, as it means the basic functionality will be unafected if javascript is disabled. But it's also confusing. Someone might click on the link out of habit (that's what links are for, right ?) and get confused by the glimpse of the tooltip appearing as the page starts scrolling down.

That's pretty much what Wikipedia does, and while it works well on their page, here it just feels wrong and annoying. Feels like we need to tune the numbers just right on the animation delays and whatnot, which sounds like the polar opposite of fun.

Well. The intent behind these tooltips is mostly to add some jokes or slight digressions. I don't expect to write the kind of stuff that warrants a more disciplined approach to citations or bibliography. So I could just hide the bottom list and only keep the funny tooltips. Also, I said earlier that I wasn't a fan of the usual, back and forth behaviour. So let's just get rid of the list, and problem solved, right ? We end up with just what Shamus had, only slightly nicer as I don't have to click the mouse anymore to see the silly bits.

So that's what I did. Clean up the code, slap a quick preventDefault() on the click event, and we're done. Nice and quick, still felt pretty good about it all.

That's about when I decided to document this whole process and turn this thing into an article. Obviously, I started playing with the tooltips immediately. And as I got to the second or third one I tried to include a link and...

Wait.

Kid facepalming

This2 is what it looked like. Go ahead, try and click the link.

This is hell, right ? And the worst part is, even if you could get to the damn thing, it wouldn't work anyway.

I'm copying the footnote's text into an element attribute. All the actual html markup is stripped out. You can't even see the link, because, well, there is no link.

Now, I could just accept this limitation and keep things as they are. Art lives on constraint and all that. And honestly, as long as you stick to plain text, the quick and dirty solution is fine.6 But now that I thought of stuffing links in those tooltips, I just can't let go of the idea. Without them, the whole feature is just a cute trick. But with them, it becomes actually useful, and can be a great way to add some precisions without cluttering the main point.

Also, I realize only now than the hover event won't be available on mobile, which sucks, I guess. If you were wondering why my exemples didn't work, now you know why.

Oh well, it's not like my initial approach was hugely complicated anyway. So let's get to it.

Lessons learned (?)

About 30 minutes later I got the DOM shuffling version working. The first pass was about 30 lines of pretty straightforward code. It's barely more complex than what I had before and it does what I want. Problem solved, for real this time.

So, is there even a point to this whole thing, or did I just decide to waste your time like I wasted mine ?

This story hopefully illustrates a few classic blunders. Beginners' mistakes, really, but those things have a tendency to keep happening even when you'd like to think you know better.

Diving in a rabbit hole

Rabbit staring down a hole in the ground.

When I found out I couldn't hover the tooltip themselves, my first impulse was to double down. Keep things as they are and add some logic to handle the corner cases. Which often leads to discovering more corner cases.

Sometimes there's just no way around it. But it always pays to stop as soon as you notice this pattern and think about whether or not the first steps you took were heading in the right direction.

I'm not a frontend guy. I'm bad at UI and I know it. I don't think this particular case would have gotten too bad, but that's just an assumption. The truth is that I haven't done a lot of integration work before, and most of it relied on third party libraries to handle that kind of things. Here in vanilla land, I don't have a good hunch to try and predict potential pitfalls before falling into them. I can't know how long the path is before I walk it.

Luckily I saw that one coming before embarking on a wild goose chase, but that's only because I've been burned before.7

Simple != Easy

I'm more and more convinced of the importance of the KISS principle, and I try to apply it whenever I can, even though I still fail to resist the urge of overdoing things pretty often.8 But I think my mistake here was to confuse simple and easy.

Sure, manipulating the DOM is a bit more cumbersome than simply setting an attribute. I'll have to catch up on the API, read some docs, maybe re-learn a few javascript quirks. But is it that much more complex than the naive approach ? Not really. And since the elements are copied as is, unforeseen situations where they stop behaving like they should are much less likely. No special UI shenanigans to worry about. The code is dumb and only cares about the one thing it's supposed to do. This is always better than trying to be clever.

By trying to cut corners, I was giving up all of this and would have quickly ended up with a ball of mud, ie more complexity.

I'm sure someone more used to building interfaces would have spotted the problem right away. That's what domain experience is all about. But sadly, experience doesn't always transfer well across domains, even when those look similar. Whenever you try your hand at something you're not that familiar with, chances are you'll hit that kind of wall.9

Usable != Sexy

Wooden saw lying on a wooden surface

I'm no designer, but I've been using the web long enough to develop an eye for stupid UI trends, and find myself ranting about those more and more.10 It usually boils down to something along the lines of:

"Congratulations for being such a shiny turd. Too bad you're still turd."

And yet, I still fell for the sexyness of on-hover tooltips.

There's nothing wrong with some cheap flash now and then. But doing it right is extra work, the kind of which I can only enjoy for so long before going postal and sending death threats to Brendan Eich and Håkon Wium Lie.

And half-assing it is even worse. Trigger on hover feels nicer at first thougth (why waste two mouse clicks just to read some side comments ?), but it comes with a bunch of downsides. My naive implementation4 forces you to keep your mouse in just the right spot to keep reading the damn thing. If you Alt-Tab to quickly check on something else and come back, the tooltip animation plays again, which feels like some kid waving for attention. And that's assuming you haven't moved the mouse in the meantime (if you did, then the tooltip is gone, so you have to find it back and re-hover it if you weren't done reading it). They're also prone to trigger when you're just reaching for something else. What felt sleek and modern on first impression ends up being a royal pain in the butt.

Thinking back on the Wikipedia example, I realize how good of a job they did. Their tooltips are timed just right and get out of the way seamlessly (I don't remember ever getting pissed at them. And I get pissed at crappy widgets on a daily basis). And their perfect positioning lets you interact with their contents without having to think about it. The only flaw I can find is the Alt-Tab one.

"Sexy" might not be the first word that comes to mind when thinking about Wikipedia's UI, but the best interfaces are the ones you don't even notice. Whoever did that knew what he was doing.11

Trying to replicate it could be a worhtwhile learning project. Could even be fun. But that would still take time and require me to care more that I currently can (I already spent way too much time just trying to make the stupid popups look not-quite-atrocious. Also, this was supposed to be a quick hack, remember ? It's been 3 days already. Granted, most of that was spent writing this article, but still).

I go back to Shamus' site and fiddle with his take on tooltips. His clunky, archaic take that requires pressing buttons and doesn't even try to be fancy. And I realize how right he got it.

Context is everything. This isn't wikipedia. Their implementation might be pretty cool, but it's overkill for this site. But I still want to focus on writing, and going for flash without putting in the work to do it right would just be distracting.

Sometimes the dumb and boring way is the best one.12

Are we done yet ?

I swear I didn't plan for this. This started as a simple excuse to just write something and justify getting this blog online. And as the brain got rolling it kept getting caught on details and tidbits it found interesting.

This whole tooltip thing is definitely not worth so many words by itself. No one is gonna learn anything of technical value here. But I hope this report helps demonstrate how simplicity is a tricky thing.

Even the most trivial tasks desserve some attention put into them, and following the trains of thought it produces can lead to some interesting insights. This ain't no grand revelation, but my understanding of what good UI truly is (and my conviction that it's not about making stuff bright and shiny) just grew a teeny little bit better.

I hope the bad Shamus Young impersonation wasn't too cringy. Some of it was intentional and meant as a small tip of the hat, but I didn't plan to rip him off so much. Guess I wasn't kidding when I said he was such an influence on me. Again, if you don't know his blog, go and give it a glance. If you're interested in coding (even from a distance, those posts are meant for non-tech people), I recommend his programming series. If you're more into story and worldbuilding analysis, then read one of his videogame retrospectives. Oh, and if you're a fan of DnD and/or the lord of the rings, then you can't miss his DM of the Rings comics series (they're currently being re-posted in higher quality by his family, if you'd rather follow along weekly than binge-read it all) (Oh, and apparently there's a french version too. Nice!).

Whatever your jam is, this site desserves some traffic. It's one of those places that made the web such a magical place.

Allright, I'm done. See ya interwebs!5

Tadaa! Wait... Why does *this* tooltip look different ?

Some link to the best thing you'll ever see

Filler content

Here it is again, just as a reminder. Feel free to experiment with it and marvel at how cursed it really is.

One more for the road. I promise i'll try not to overuse those so much in the future. So long!


  1. Check out my first article if you're not sure what said default behaviour is. 

  2. Did someone say regex

  3. And here goes the pride and joy of owning a 100% js free website... Oh well. It was good while it lasted. 

  4. Not on this page, though. As you probably guessed already, I'm reimplementing what I had to demonstrate how it worked. I'm not going to redo everything just as it was, though. Sorry if this makes things confusing. 

  5. Although the version I posted and kept for this article is slightly naive. You need to clean up the textContent to remove the footnote's backlink and the extraneaous white space that messes up the formatting. No big deal, but thought I'd mention it in case someone wants to use the posted code (Pro-Tip: use a regex, it'll be cleaner than chaining trim calls as I did. Don't worry. It's not HTML anymore). 

  6. and likely will again 

  7. As soon as I got the cleaner script working, I went ahead and added a bunch of options to customize the behaviour, knowing full well this code is probably never gonna leave this site. Sigh. 

  8. Keep that in mind next time you feel like poking fun at some job because it looks easy. 

  9. Hell, I'm even thinking about a dedicated category for those rants. For now, I'll just link to thisfor an appetizer. 

  10. I didn't even mention the settings link that lets you tune the whole behaviour to your liking. Man, what a class act. 

  11. This article would have been a lot shorter if I had just gone with my first idea. I'm not sure whether this would have been a good or a bad thing. 

^