blogccasion

<ruby> HTML footnotes

It is sometimes surprising to me to see what kind of use cases HTML has a dedicated element for. Something that comes to mind is <output>, a container element into which a site or app can inject the results of a calculation or the outcome of a user action. For another use case that is arguably more common and which is also the topic of this blog post, HTML has nothing specific to offer: footnotesFootnotes are notes at the foot of the page while endnotes are collected under a separate heading at the end of a chapter, volume, or entire work. Unlike footnotes, endnotes have the advantage of not affecting the layout of the main text, but may cause inconvenience to readers who have to move back and forth between the main text and the endnotes..

Footnotes in HTML, then and now

Despite several proposals to deal with footnotes at the language level, HTML 3.0 Draft was the last version of HTML that offered the FN element. It was designed for footnotes, and when practical, footnotes were to be rendered as pop-up notes. You were supposed to use the element as in the code sample below (the inconsistent character casing sic).

<dl>
  <dt>Hamlet:</dt>
  <dd>
    You should not have believed me, for virtue cannot so
    <a href="#fn1">inoculate</a> our old stock but we shall
    <a href="#fn2">relish of it</a>. I loved you not.
  </dd>

  <dt>Ophelia:</dt>
  <dd>I was the more deceived.</dd>

  <dt>Hamlet:</dt>
  <dd>
    Get thee to a nunnery. Why wouldst thou be a breeder of sinners? I am myself
    <a href="#fn2">indifferent honest</a></dd>
</dl>

<fn id="fn1"><i>inoculate</i> - graft</fn>
<fn id="fn2"><i>relish of it</i> - smack of it (our old sinful nature)</fn>
<fn id="fn3"><i>indifferent honest</i> - moderately virtuous</fn>

The current HTML Living Standard (snapshot from January 22, 2021) remarks that HTML does not have a dedicated mechanism for marking up footnotes and recommends the following options for footnotes. For short inline annotations, the title attribute could be used.

<p><b>Customer</b>: Hello! I wish to register a complaint. Hello. Miss?</p>
<p>
  <b>Shopkeeper</b>:
  <span title="Colloquial pronunciation of 'What do you'">Watcha</span> mean,
  miss?
</p>

<p>
  <b>Customer</b>: Uh, I'm sorry, I have a cold. I wish to make a complaint.
</p>
<p>
  <b>Shopkeeper</b>: Sorry,
  <span title="This is, of course, a lie.">we're closing for lunch</span>.
</p>

Using title comes with an important downside, though, as the spec rightly notes.

Unfortunately, relying on the title attribute is currently discouraged as many user agents do not expose the attribute in an accessible manner as required by this specification (e.g. requiring a pointing device such as a mouse to cause a tooltip to appear, which excludes keyboard-only users and touch-only users, such as anyone with a modern phone or tablet).

For longer annotations, the a element should be used, pointing to an element later in the document. The convention is that the contents of the link be a number in square brackets.

<p>Announcer: Number 16: The <i>hand</i>.</p>
<p>
  Interviewer: Good evening. I have with me in the studio tonight Mr Norman St
  John Polevaulter, who for the past few years has been contradicting people. Mr
  Polevaulter, why <em>do</em> you contradict people?
</p>

<p>
  Norman: I don't. <sup><a href="#fn1" id="r1">[1]</a></sup>
</p>
<p>Interviewer: You told me you did! …</p>

<section>
  <p id="fn1">
    <a href="#r1">[1]</a> This is, naturally, a lie, but paradoxically if it
    were true he could not say so without contradicting the interviewer and thus
    making it false.
  </p>
</section>

This approach is what most folks use today, for example, Alex Russell or the HTML export of Google Docs documents.

The ruby element

The other day, I came across a tweet by Michael Scharnagl, whose website and Twitter handle are aptly named Just Markup and who runs a Twitter campaign this year called #HTMLElementInATweet:

Day 22: <ruby>

Represents small annotations

ℹ️ The term ruby originated as a unit of measurement used by typesetters, representing the smallest size that text can be printed on newsprint while remaining legible.

developer.mozilla.org/en-US/docs/Web…

#HTMLElementInATweet

— Michael Scharnagl (@justmarkup) January 22, 2021

I had heard about ruby in the past, but it was one of these elements that I tend to look up and forget immediately. This time, for some reason, I looked closer and even consulted the spec.

The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana.

The rt element marks the ruby text component of a ruby annotation. When it is the child of a ruby element, it doesn't represent anything itself, but the ruby element uses it as part of determining what it represents.

You are supposed to use it like so.

<ruby> 明日 <rp>(</rp><rt>Ashita</rt><rp>)</rp> </ruby>

The MDN docs describe the ruby element as follows.

The HTML <ruby> element represents small annotations that are rendered above, below, or next to base text, usually used for showing the pronunciation of East Asian characters. It can also be used for annotating other kinds of text, but this usage is less common.

The term ruby originated as a unit of measurement used by typesetters, representing the smallest size that text can be printed on newsprint while remaining legible.

Hmm 🤔, this sounds like it could fit the footnotes use case. So I went and tried my luck in creating ruby HTML footnotes.

Using ruby for footnotes

The markup is straightforward, all you need are ruby for the footnote, and rt for the footnote text. I like that the footnote is just part of the flow text, so I do not need to mentally switch context when writing. I also do not have to manually number my footnotes and come up with and remember the value of ids. Another small advantage is that footnotes are not part of copied text, so when you copy content from my site, you do not end up with "text [2] like this". The snippet below shows the markup of a footnote.

<body tabindex="0">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec consectetur
    dictum fermentum. Vivamus non fringilla dolor, in scelerisque massa. Quisque
    mattis elit quam, eu hendrerit diam ultricies ut. Nunc sit amet velit
    posuere, malesuada diam in, congue diam. Integer quis venenatis velit. Donec
    quis nunc
    <ruby tabindex="0"
      >vel purus<rt
        >Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      </rt></ruby
    >
    maximus dictum. Sed nec tempus odio. Vestibulum et lobortis ante. Duis
    blandit pulvinar lectus non sollicitudin. Nulla non imperdiet diam. Fusce
    varius ultricies sapien id pretium. Praesent ut pellentesque massa. Nunc eu
    tellus hendrerit risus maximus porta. Maecenas in molestie erat.
  </p>
</body>

The CSS to make the automatic footnote numbering work is based on a CSS counter. The rt is styled in a way that it is not displayed by default, and only gets shown when the ruby's :after, which holds the footnote number, is focused. For this to function properly, it is important to make the <ruby> element focusable by setting tabindex="0". On mobile devices, the body needs to be focusable as well, so the footnote can be closed again by clicking/tapping anywhere in the page. The rt element can contain phrasing content, so links and images are all fine. Another thing to remember is to make sure the rt element remains visible on :hover, so links can be clicked even when the ruby element loses focus. I have moved the CSS display value of rt into a CSS custom property, so I could easily play with different values. The CSS below is all it takes to make the footnotes work.

/* Behavior */

/* Set up the footnote counter and display style. */
body {
  counter-reset: footnotes;
}

/* Make footnote text appear as `inline-block`. */
ruby {
  --footnote-display: inline-block;
}

/* Display the actual footnote [1]. */
ruby:after {
  counter-increment: footnotes;
  /* The footnote is separated with a thin space. 🤓 */
  content: ' [' counter(footnotes) ']';
}

/* Remove the focus ring. */
ruby:focus {
  outline: none;
}

/* Display the footnote text. */
ruby:focus rt {
  display: var(--footnote-display);
}

/* Hide footnote text by default. */
rt {
  display: none;
}

/**
 * Make sure the footnote text remains visible,
 * so contained links can be clicked.
 */
rt:hover {
  display: var(--footnote-display);
}

The following CSS snippet determines the look and feel of the footnotes.

/* Look and feel */

/* Footnote text styling. */
rt {
  background-color: #eee;
  color: #111;
  padding: 0.2rem;
  margin: 0.2rem;
  max-width: 30ch;
}

/* Images in footnote text styling. */
rt img {
  width: 100%;
  height: auto;
  display: block;
}

/* Footnote styling */
ruby:after {
  color: red;
  cursor: pointer;
  font-size: 0.75rem;
  vertical-align: top;
}

Something I could not get to work (yet) is to make the rt's CSS position to be absolute. I got the best results so far by making the rt an inline block by setting the CSS property --footnote-display: inline-block. I am well aware of ruby-align and ruby-position. The former does not have great browser support at the moment but seems relevant, and the latter seems to have no effect when I change the display value of rt to anything other than the UA stylesheet default, which is block. If you manage to get it to work such that footnote texts open inline, floating right under the footnote and not affecting the surrounding paragraph text, your help would be very welcome. I also still need to look into supporting printable footnotes, screen reader support, and fixing the RSS feed. If you are interested, you can reach me and discuss this idea on Twitter.

Demo

I have enabled ruby footnotes right on my blog This is the second footnote, the other is at the top., but you can also play with a standalone demo on Glitch and remix its source code.

⚠️ Please note that this is not production ready. Support seems decent on Blink/WebKit-based browsers, but not so great on Gecko-based browsers like Firefox. I have opened an Issue with the CSS Working Group to hear their opinion on the idea, and the response was:

Although ruby was introduced to HTML & CSS primarily because of its use in Asian languages, nothing about it is specific to that. Similarly, although it is often used to give a phonetic pronunciation, ruby is not specific to that so other uses are okay.

And yes it is really odd that HTML has nothing for directly expressing an inline note (a footnote is just one presentation possibility, more suitable to paginated content).

So I would not say it is an abuse. It is a bit creative, but mostly because people only think of the most common use cases.

Other approaches

The "standards nerd and technology enthusiast" Terence Eden proposed to use details in a blog post titled A (terrible?) way to do footnotes in HTML. Next, Peter-Paul Koch, web developer, consultant, and trainer, runs a side project named The Thidrekssaga and footnotes where for the current iteration of the site he just notes that his "implementation of footnotes is mostly shit". If you have yet another approach apart from what is listed here and above, please reach out and I am happy to add it. And as I wrote before, I am looking for help from CSS experts to make rt positioned absolutely. Sorry for the nerd-snipe.