By Hugo Giraudel

Accessible Footnotes with CSS

By Hugo Giraudel

I was playing with CSS counters the other day and thought about using them to deal with footnotes. According to Plagiarism which has a surprisingly long entry on the matter, footnotes are:

[…] notes placed at the bottom of a page. They cite references or comment on a designated part of the text above it.

You often see them in papers when the author wants to add a piece of information or cite a reference without doing it in the middle of the content or using parentheses. Usually, footnotes are represented with a number according to the position of the footnote in the document, then the same numbers are present at the bottom of the document, adding extra content.

The problem with footnotes on the web is that they can be a pain to maintain. If you happen to work on the same document often, changing the order of sections, adding references along the way, it might be tedious to have to re-number all existing footnotes. For example, if you have 3 existing references to footnotes in a document, and you want to add another one, but on a piece of content that occurs before all the others, you have to re-number them all. Not great…

We could use CSS counters to make this whole thing much easier. What if we did not have to maintain the numbering by hand and it could be done automatically? The only thing we would have to pay attention to, is that the order of the actual notes in the footer respect the order of appearance of the references in the text.

Creating a sample document

Let’s create a sample document so we can get started.

  <h1>CSS-Powered Footnotes</h1>

  <p>Maintaining <a href="#footnotes">footnotes</a> manually can be a pain. 
  By using <a href="#css">CSS</a> <a href="#css-counters">counters</a> to add 
  the numbered references in the text and an ordered list to display the actual 
  footnotes in the footer, it becomes extremely easy.</p>

      <li id="footnotes">Footnotes are notes placed at the bottom of a page. They 
      cite references or comment on a designated part of the text above it.</li>

      <li id="css">Cascading Style Sheets</li>

      <li id="css-counters">CSS counters are, in essence, variables maintained by 
      CSS whose values may be incremented by CSS rules to track how many times 
      they're used.</li>

Our example is lightweight: we have some content in an <article> element, which contains some links (<a>) pointed at in-document IDs, mapped to the notes in the <footer> of the article.

With a few styles, it might look like this:

Accessible footnotes with CSS – raw version

Making it accessible

Before actually getting onto the counters thing, we should make sure our markup is fully accessible for screen-readers. The first thing we want to do is add a title to our footer that will serve as a description or our footnote references. We’ll hide this title with CSS so it doesn’t show up visually.

  <h2 id="footnote-label">Footnotes</h2>

Then, we want to describe all our references with this title, using the aria-describedby attribute:

<p>Maintaining <a aria-describedby="footnote-label" href="#footnotes">footnotes</a> 
manually can be a pain. By using <a aria-describedby="footnote-label" href="#css">CSS</a> 
<a aria-describedby="footnote-label" href="#css-counters">counters</a> to add the 
numbered references in the text and an ordered list to display the actual footnotes 
in the footer, it becomes extremely easy.</p>

Now screen reader users will understand when links are references to footnotes.

Adding the references

I know what you’re thinking: He said there would be CSS counters. Where are the CSS counters? Well worry not, my friend, they are coming.

What we are going to do is increment a counter for every link in the document that has an aria-describedby attribute set to footnote-label. Then we’ll display the counter using the ::after pseudo-element. From there, it’s all about applying CSS styles.

 * Initialiazing a `footnotes` counter on the wrapper
article {
  counter-reset: footnotes;

 * Inline footnotes references
 * 1. Increment the counter at each new reference
 * 2. Reset link styles to make it appear like regular text
a[aria-describedby="footnote-label"] {
  counter-increment: footnotes; /* 1 */
  text-decoration: none; /* 2 */
  color: inherit; /* 2 */
  cursor: default; /* 2 */
  outline: none; /* 2 */

 * Actual numbered references
 * 1. Display the current state of the counter (e.g. `[1]`)
 * 2. Align text as superscript
 * 3. Make the number smaller (since it's superscript)
 * 4. Slightly offset the number from the text
 * 5. Reset link styles on the number to show it's usable
a[aria-describedby="footnote-label"]::after {
  content: '[' counter(footnotes) ']'; /* 1 */
  vertical-align: super; /* 2 */
  font-size: 0.5em; /* 3 */
  margin-left: 2px; /* 4 */
  color: blue; /* 5 */
  text-decoration: underline; /* 5 */
  cursor: pointer; /* 5 */

 * Resetting the default focused styles on the number
a[aria-describedby="footnote-label"]:focus::after {
  outline: thin dotted;
  outline-offset: 2px;

Now it looks like this:

Accessible footnotes with CSS

Pretty nice, huh? As a final touch, when heading to a footnote from a reference, we want to highlight the note in the footer so we actually see what is the note being referred to, which we can do using the :target pseudo-class:

footer :target {
  background: yellow;

It is a bit raw, so feel free to customise. Although I must say I like the pure yellow for a highlight – it looks so authentic:

Accessible footnotes with CSS – A footnote is targeted

Our demo needs one final element to be fully accessible (as well as pretty cool): back-to-content links. Think about it: You focus a reference, head to the relevant note in the footer, read it and then… nothing. You need a way to go back to where you left!

Providing those links is not that hard: we only need to add a unique ID attribute to each reference in the content so they can be linked to. I decided to go simple and take the ID they refer to, and simply append -ref to it:

<p>Maintaining <a aria-describedby="footnote-label" href="#footnotes" id="footnotes-ref">footnotes</a> 
manually can be a pain. By using <a aria-describedby="footnote-label" href="#css" id="css-ref">CSS</a> 
<a aria-describedby="footnote-label" href="#css-counters" id="css-counters-ref">counters</a> 
to add the numbered references in the text and an ordered list to display the actual 
footnotes in the footer, it becomes extremely easy.</p>

Then each list item from the footer has its own link heading to the relevant id we just added. The content of the link is the backlink Unicode icon (↩), and it has an aria-label attribute with a value of “Back to content”.

  <li id="footnotes">Footnotes are notes placed at the bottom of a page. 
  They cite references or comment on a designated part of the text above it. 
  <a href="#footnotes-ref" aria-label="Back to content">↵</a></li>
  <li id="css">Cascading Style Sheets 
  <a href="#css-ref" aria-label="Back to content">↵</a></li>
  <li id="css-counters">CSS counters are, in essence, variables maintained 
  by CSS whose values may be incremented by CSS rules to track how many 
  times they're used. <a href="#css-counters-ref" aria-label="Back to content">↵</a></li>

To target those links in CSS, we can rely on the aria-label attribute the same way we did for aria-describedby:

[aria-label="Back to content"] {
  font-size: 0.8em;

Here is what the final demo looks like:

See the Pen Accessible footnotes with CSS by SitePoint (@SitePoint) on CodePen.

Final thoughts

With nothing but a couple of lines of CSS and a few ARIA attributes, we managed to create CSS-powered footnotes that are accessible and do not need any JavaScript. How cool is that?

On topic, I highly recommend Semantic CSS with intelligent selectors from Heydon Pickering. Also, be sure to check out a11y.css from Gaël Poupard to check the accessibility of your pages.

Huge thanks to Heydon Pickering for his valuable help regarding accessibility in this demo.

  • Ralph Mason

    Really great writeup, Hugo! I’ve been pondering this issue for a while now, and this is a really nice solution.

  • Gäst

    One up on this. I had never heard of css counters before either!

  • Michael Sohn

    Awesome! I like that the footnote number actually refers to a part of the text, be it the previous word, a few words or the whole sentence. Regarding semantics that’s much better than just appending it. One suggestion: You could add `[aria-describedby=”footnote-label”]:target` to the rule highlighting the target to make the journey full circle.

  • Amelia Bellamy-Royds

    Great overview. I think this nicely summarizes best practices for footnotes in HTML.

    Nonetheless, I’m really looking forward to better page float layout options, so you can include the footnote text right in the markup where you reference it, and have it float down to the bottom of the page, in the correct order, all by itself — so you don’t have to manually re-order your footnotes if you re-order the text!

    • You could probably already hack something like this with CSS regions.

      • Dave Hope

        Chrome dropped the support and the overall support is very low. Do you have any other idea as a solution for that problem, Hugo? I’m writing my bachelor thesis right now and would really love to publish in html/css :D

    • Peter Weil

      I kind of agree. Footnotes come from the print world, and migrating that model to the web (done very well here) raises a question in my mind about semantics. The only semantic linkage, if you can call it that, between the reference and the note is a link. Maybe the two ought to be together in the markup. Perhaps that would make the content not “flow” as well, but if that’s the case then perhaps it ought to be rewritten.

    • Dave Hope

      This is so true Amelia! Without this feature, printing of longer documents makes absolutly no sense. You can use some sort of converters but that feels so strange, that I could also use Indesign.

  • Daniel Tonon

    Love this :) I’d make one small change though. I’d give each li in the footnotes list tabindex=”0″ and swap the highlight styling from the :target state to the :focus state. It would provide better keyboard accessibility.

    That way, you tab to the reference number > press enter > get taken to the list item > press tab > focuses on the back link > press enter > takes you back to where you were.

    I’m pretty sure that with your current code, you press tab after going to the footnote list and it would focus on the very first link on the page instead of focusing on the back link like you would expect it to.

  • Nicolas Hoffmann

    This makes me remember SPIP footnotes, which are really user-friendly to use.

    Clever use of ARIA :)

  • As you’re hiding the Footnotes heading for visual users, you could just skip the element entirely and use aria-label=”footnotes” on the footer element.

  • Very cool! FYI webkit in-page link bug is affecting your demo, keyboard accessibility is not actually sending TAB focus down to the footnotes for a keyboard user.

  • Richard

    Nice, but if the order of the footnotes in the article changes, you *still* need to manually change the order of the footnotes in the list. Otherwise, your footnote links will have the wrong number.

  • Gumnos

    I’ve done something similar to this before. The problem is that I have to touch disjoint parts of the document. I’d really love to find a CSS-only way of keeping the footnotes’ content in-line with the referencing text, but then have the footnotes display elsewhere in a footer like this does. I’ve done that with JavaScript, but have been unable to do it in pure CSS. Any ideas on that?

  • This is very cool Hugo.

    FWIW, here’s a personal take on improving (questionable though) this idea.

    Since the links are getting styled like the copy/text surrounding them, I’m assuming the intent is to click on the footnote label rather than on the link itself, otherwise the link would’ve stayed styled like a, well, a link.

    With this being said, I would add pointer-events: none; to the a[aria-describedby="footnote-label"] selector.

    Then add pointer-events: auto; to the a[aria-describedby="footnote-label"]::after selector to bring back the link functionality but only to the footnote label.

    Here’s a Pen:

    A few notes before the usability gods send their wrath on me:

    * The footnote labels are incredibly small by definition, removing the link on their parent element very likely makes them more difficult to use.

    * I would prefer to style the footnotes’ lables links rather than remove their functionality, but I just wanted to adhere to Hugo’s article and style.

    * I did this FTFOI (not sure if that accronym even exists) and because I wanted to see if I could successfully remove the default behavior of the parent link but bring it back to the footnote element.

    * By doing this I learned about using pointer-events: auto; and this article in MDN: pointer-events


  • Very cool

  • I am coming back to this after a while and took time to re-read and consider all your comments. I updated the demo with a lot of your interesting thoughts, although the embedded CodePen is from SitePoint account, not mine so here is the updated version:

    Kudos to @danieltonon and @davidstorey.

  • CarolonthePlains

    Sweet! Works beautifully.

Get the latest in Front-end, once a week, for free.