I might have just solved footnotes on AO3? More specifically, I’ve developed tricks for displaying text popups using only HTML and CSS, so this works on sites like neocities too.
Now, I’m not super tapped into the state of the art for AO3 workskins, it’s possible and indeed very plausible to me that I’m not actually the first to think of some of this. AO3 is an old site and everything I’m using is just a clever combination of features HTML has had for decades.
But as far as I’m aware—though my experience is just existing in a couple of small fandom communities and making a half-hearted google search—I know of three main ways you can implement footnotes.
Dead simple: just put <sup>1</sup> in the chapter, and expect the reader scroll down or keep another tab open to crossreference the endnotes. (Or just keep the footnotes nearby.)
Standard trick: just use anchor links (e.g. <a id="from-fn1" href="to-fn1">1</a>) to auto scroll down to the end, where a matching link (<a href="from-fn1">↩︎</a>) will take you back to the top. This is what many tutorials recommend, and it’s what conversion software like pandoc will spit out.
Advanced trick: include the notes in the workskin, coded so that when you hover over the link the note will expand out inline.
That the first of these sucks goes without saying.
The second one is decently functional—most existing sites with footnotes do this. I find it interrupts the reading experience pretty badly, and the juice is perhaps not worth the squeeze, when you’re doing that whole jarring transition just for a quick joke from an author who may or may not actually be funny.
The third one is pretty nice… with a lot of technical warts. Editing the CSS instead of the actual content is extremely inelegant, requires a unique skin per fic, makes you deal with quote weirdness, and you can’t use italics or other formatting. On top of that, readers with workskins disabled (or those exported the text) will lose your notes entirely.
Finally the mobile experience with these hover-centric approaches can often be hit or miss. (Worse, there’s no “the” mobile experience, since some, like iOS, have browsers with special behavior to interact with hover elements.)
So, what does my solution look like?
Lorem ipsum dolor sit amet consectetur adipiscing elit nulla, tempor sodales tellus condimentum leo parturient etiam iaculis, pretium pharetra velit placerat suspendisse nullam augue.Enim mus congue dui sapien pellentesque lacus. Vitae feugiat taciti iaculis ante hendrerit tempus morbi cubilia platea cursus, sapien sagittis porta fermentum proin bibendum congue lacus sodales, nam cras hac torquent ut orci pellentesque turpis ac.Egestas conubia aenean non rutrum ligula hendrerit venenatis class mattis, sed praesent eget quisque vehicula tortor urna nisl, suspendisse cum elementum sollicitudin donec fermentum curae per. Conubia elementum egestas ridiculus aptent dis, hendrerit luctus est curabitur montes, euismod hac nisl sagittis.Massa enim sociis rhoncus convallis sollicitudin sagittis fames nunc,…varius neque scelerisque magna per tortor aptent ullamcorper sociosqu… taciti leo pellentesque fusce est inceptos vitae.
Feugiat class torquent quisquenoteLigula! Ligula id imperdiet! odio hendrerit neque lacus senectus cras,Aptent duis litora condimentum id phasellus eros felis auctor potenti aliquet lacinia, nostra sem gravida imperdiet netus sapien nascetur quam consequat quisque. dictum sollicitudin nisl posuere accumsan hac pulvinar leo tellus, ullamcorper viverra risusLigula id imperdiet mollis eros penatibus himenaeos fermentum cubilia, praesent lacus lobortis nibh sollicitudin arcu massa class fames, morbi suscipit diam odio malesuada aenean mattis. commodo parturient mi taciti platea.
Auctor at sodales taciti felis litora eu hac nec turpis, quisque fringilla conubia orci dignissim nascetur mollis class dapibus erat, tempus pharetra sagittis euismod elementum luctus maecenas dictum.note Ridiculus feugiat praesent donec tincidunt in parturient vitae etiam quam, bibendum pulvinar eros quisque faucibus at felis lobortis, sem semper netus est tellus ornare habitant diam.note
Dictum morbi facilisi cum himenaeos penatibus mattis fringilla maecenas, lobortis euismod hac ridiculus gravida mollis donec, sociis risus auctor quisque ante inceptos molestie. Fermentum magnis posuere rutrum interdum a tellus hac urna, ridiculus proin tempor penatibus euismod tortor massa vehicula, libero senectus eros sagittis fames suspendisse vulputate.
Footnotes
Potenti auctor lobortis nascetur eu donec himenaeos quisque velit, aptent tellus nullam proin fusce iaculis rhoncus dictumst pretium, hac cursus porttitor ornare magnis mattis erat.
Vulputate inceptos pellentesque donec consequat tempor dignissim fermentum parturient, ullamcorper erat id vivamus ad turpis a faucibus laoreet, dapibus tortor pulvinar blandit nec dui feugiat.
This code offers three different styles of notes. They share a trick in common. See, the standard approach to doing footnotes is to add an anchor link to a different part of the document. But what if we kept the notes inline? It turns out CSS offers the :target selector, which matches the element currently anchored to. (It’s the bit after the hashtag in your url part. For example.)
Thus, we can make our inline note disappear whenever we aren’t anchored to it, by tucking it into a span that’s hidden unless a preceding link gets the anchor. (We use links for this in part because it’s the only element AO3 allows to keep its ID.)
Of course, if we get that working, next we’ll want a way to close the notes after we’ve read them (generally you’re footnoting to avoid breaking up the flow of the text), so we need another link pointing somewhere other than at the first link.
My initial approach was two links, each with a unique id, linking to themselves. Click the first link and the note will appear along with the second link, which mainly serves to move the anchor target off the first link and thereby close the note (thus making the first link appear again). This first attempt might look like:
This works, but if you implement it exactly how I’ve described it thus far, you’ll notice an odd little inconsistency. Clicking the first link causes a ‘jump’ as the browser scrolls so that it’s at the top of the window. This is exactly what we complained about with the ‘standard’ approach, but at least this jump will keep in sight (most of) the text you were already reading.
But I said it’s inconsistent. It only jumps if you open the note; when you close the note, there’s never a jump. Weird! But hey, it does work, so I might have called it a day there. Then, when I was writing up my progress in a chatroom, I realized exactly what was happening.
Each anchor links to itself. The second link is only visible if the first link is the anchor target. Meaning that when you click the second link, it disappears. When you click an achor link to an element not on the page—well, try it!
See? Nothing happens.
We can use this. Thus, the current version is coded so that the link targets are invisible whenever they are anchored to—an element will still be the :target even when not displayed.
That’s all the important stuff; some other details are cosmetic. I make the text smaller and add margins so that it looks appropriate, I make it inline-block so that short notes seamlessly fit into the text, while longer ones are set apart.
But that’s not what most people want out of their inline notes, is it? At first, the first paragraph of my demo was all I had to show off in the chatroom. People thought it was great! But of course, in an ideal world, the note would float above the text rather than breaking it up, wouldn’t it?
Now, this was actually entirely doable. Long time readers of this site know that I’ve had inline notes implemented here for a while, and they used to float.
But I decided keeping them inline made for a better reading experience; I settled on that during a redesign, and thoughtlessly copied that when cooking up these new notes.
Floating is doable, yes, but it took some working to recreate it; I had forgotten what I had actually done all those months ago, and stumbled into the same bugs over again.
But I would caution any writers thinking of using my floating notes, even though they might be exactly what you want. One of the strengths of AO3—the very thing that lets us have this conversation—is that its skin system lets you define your own CSS. In particular, default AO3 is white text on a white background, while one of the popular preset skins (Reversi) is dark mode. To say nothing of whatever bizarre schemes users can code up for themselves.
In order for the floating boxes not to blend in unreadably with what they float over, they need a background color. What color? My knowledge of CSS provides me with no way to inherit background colors.
So you have to pick one, perhaps one that suits the mood of your fic. But if you’re setting the background, you’ll need to set the foreground, too, lest someone read your fic with a theme that offers no contrast to that background. And once you’re defining both of those, you risk the whole thing looking awfully out of place.
None of this is the end of the world, and my guess—no stats, just vibes—is that if you can make it look alright in default AO3 and Reversi, that accounts for most of the people who’ll read your fic.
But again, all of that is why I say just use inline notes, they’ll fit right in even if your fic lures in someone rocking the hotdog skin.
With all of that said… I’ve done this much, why not flex a bit more? But this last style of footnote has a bit more to motivate it than flexing.
One thing I believe bears consideration whenever you’re doing crazy things with workskins is to remember that AO3 provides a button right at the top of your fic to disable all of your fun.noteAnd if they download an offline copy of your fic, it likewise won’t retain any CSS.endnote
And that’s to say nothing if someone is using an ancient or niche browsernote(Hi Lynx.)endnote with spotty or buggy CSS support, or they’re blind, or plenty of more unexpected possibilities.
So, what do these notes look like without CSS? Well, I’ve thought of that for you. If you use the template I’ll provide in the next section, it’ll also insert [ and ] around your note. The workskin snippet will hide everything in the note element except the links and the text, so most readers won’t see it, but those exceptional few will simply have a oddly parenthetical-heavy reading experience.
But can we do better than this? Turns out, we can! In fact, we can almost directly replicate the experience of glancing to the bottom of the page to read the footnotes.
Armed with the knowledge that hiding anchors prevents scrolling, we don’t even need our anchors to be anywhere near their links. CSS offers position: sticky for making elements hang around when you scroll. If we put our notes back at the end of the document—same as standard—but tweak things so that anchored notes become fixed, then clicking on a note will sort of yank it up to where the reader can see it. Add a link to nowhere at the end to dismiss it, and we’re cooking.
This last approach has the advantage of not squirreling away text into hidden crevices; every footnote can be found by scrolling to the end.
My implementation of these “true” footnotes has a few more features added for polish. Notably, I use a slick little switcharoo with the return links: if the footnote is floating, it only dismisses the popup, but if you scroll down to the bottom, you’ll see a different but identifical link: clicking that one will scroll you up to where they were linked in the text.
At this point, you might be itching to try this all out. Let’s get on with that.
Replace TEXT the contents of the note, and ID with a sequence of number or letters unique to this note. If you forget or duplicate an ID, the note may not open when clicked.
Now you should be good to go. Specifically, doing this will give you:
TEXT is hidden by default, and only the first link is displayed
Links will say “note” by default. If you add any text before the first </a>, it will override this. (e.g. † or 1).
If you click the link, TEXT will appear, and the link is hidden, and the second link appears in the same place.
If you click the second link, the note is once again hidden
If you hover over the link, the note will appear, slightly transparent.
if the <span class="note"> is changed to <span class="note no-hover"> then the hovering behavior is suppressed.noteGood for longer notes, though it may be better to consistently pick one or the other.endnotenoteAlso, one incredibly niche interaction to be aware of is that hover does not play nice with justified text; the expansion of the note will cause a reflow of the paragraph, which will change the positioning of the link, potentially ‘fluttering’ since you are no longer hovering over it. You might guess that I only just now noticed this when proofreading everything on this site.endnote
If the <span class="note"> is changed to <span class="note float"> then the note will float over the text instead of appearing inline.note(You can combine this with no-hover in a way I hope is obvious.)endnote
Footnotes require different code. Put this where you want the link to appear:
(ID is once again selected to be unique, and ‘note’ may be replaced with a symbol or number of your choice. It probably should be a number, for clarity’s sake.)
Put this where you want the footnote to reside (e.g. at the end of the chapter), with the same ID:
<a class="fn-anchor" id="fn-ID"></a><div class="footnote"
>TEXT<
a href="#-"></a><a class="fn-back"
href="#from-fn-ID"></a></div>
A minor limitation to be aware of is that you can only have a single note open at once; clicking another closes the one already opened. In particular, this means nested notes do not work out of the box.
This is fixable; the workskin provided includes code specifically for displaying notes-within-notes, but making them actually work requires careful attention to the HTML. Specifically, the link with href="#-" must be changed to say href="#fn-PID" where PID is the ID of the note containing the sub-note.noteThe truly creative among you might already be realizing PID doesn’t have to be the parent’s ID — indeed, because these are just links, and we patched the scrolling jank, you can simply have a link to #fn-whatever and open a note on the other end of the scrollbar.endnote Also, if you’re going to nest very deep for some reason, you probably want to add a minimum to font-size or things will get ridiculous.
That’s all that comes to mind. I’ve done what I can to make this code work, checked for and fixed edge cases and polished away cruft borne of iteration and false starts. I’ve tried to keep this bare and functional—you can get fancier with the borders and hover effects, you could add box-shadows, but if you know how to do all that… well, do it.
I’m sure a CSS expert could fix this up further,noteThe floating bits in particular feel like I’m bumbling without a rich understanding.endnote but I think what I have is an improvement over a lot of what’s out there—I hope it serves you well!
If you do use this code, consider crediting me and linking back here? I’d like to have my spores out there.
This is my blog, and so this next section is mostly for my fans; those looking for the code already have it.
You may be wondering why I’m thinking so hard about footnotes when I haven’t written any fic that features footnotes and I’ve been distinctly unproductive this year. Alas, there’s nothing new in the pipeline that would require me to have a footnote system loaded into the chamber.
If anything, this project was me casting off training weights. Last month I worked hard on a much more ambitious project pushing the boundaries of what you can do with AO3’s allowed HTML and CSS—something to remind people that no one does it like me. Unfortunately, it turns out writing nearly two thousand lines of code in a few weeks while testing and refactoring it all day every day has a chance to inflict this status condition called ‘burnout’—rare stuff, don’t know if anyone’s felt this before.
But it does mean that throwing together this footnote system was comparatively trivial.
Saying that may have piqued your interest—what exactly I was writing all that code for? Well, I had first conceived it as a means to pull off the long awaited next chapter of Hostile Takeover, but before I could plan out (or even consider) the formatting tricks I was imagining, I had to prove they were even possible. So I intended to put together a much less ambitious demo.
That demo stalled out. A mix of factors, some of it was the burnout, some of it was compile time of the text growing exponentially when I’d hardly even scratched the surface of what I was planning, and some of it was just doubt about the merits of the demo.
I have faith that I will put that code to use some day, in some way.
But if you want a teaser: I do have a project name for the program I created to generate that advanced formatting. The ancient ninja technique of ⸢Izanagi⸥ was capable of turning illusion into reality and reality into illusion. For a brief moment of time, anything disadvantageous to the user, such as damage or death, could be rewritten as in a dream.