Sidenotes with HTML, CSS and Javascript

How to do sidenotes in HTML documents using CSS and Javascript

Updates since first writing

What are sidenotes?

A while ago I read footnotes on the web and none of the samples there satisfied me. I created my solution shortly after reading that, but it has been on the dark corners of my harddisk for over a month. I agreed with the author of the article that sidenotes are the best solution for footnotes on the web, therefore that's what I created.

The basic method

Footnotes are, in some degree, style-related. What is the best way to do anything style-related? Damn right, CSS. So that's what I did. The requirements? A browser which supports CSS3 media queries. Perhaps this solution wouldn't have occured to me as the most obvious one available, if it wasn't that I've been able to play around with it for quite some time already in Opera, which happens to be my browser of choice...

Let's start out. How do we markup a sidenote? Well, as HTML contains no way whatsoever to markup a foot- or sidenote, the logical choice is small. Why small? Well, it means that the content of small is less important. A footnote should not be a footnote at all if it's as important, or more important than the text itself, right? Thus, the markup of the sidenote is as follows:

<small class="sidenote">A sidenote</small>

The sidenote as I created it is meant to be put at the end of a sentence, inside a paragraph. Therefore it would be displayed at its original position in the text if author CSS was disabled, or read at its intended location on screenreaders. If it wouldn't be put as a separate sentence, it would look strange if not displayed the intended way. The sidenote is placed inside the paragraph with the other text, for if it would require multiple paragraphs, should it be a sidenote?

So how do we style our sidenote? Well, we apply some simple CSS which is required for the basic sidenote display.

.sidenote {
display: block;
float: right;
width: 200px;
border: 1px solid #000;
margin: 2px;
padding: 3px;
}

Now the sidenote will not actually be a sidenote, but more a sort of insidenote, floating right of the text. This is the basic position, which will work on all resolutions. However, to create a true sidenote, I add two simple media queries.

@media screen and (min-width: 900px), projection and (min-width: 900px), tv and (min-width: 900px) {
#container{margin-left:10px}
.sidenote {
float:none;
position: absolute;
right: 0;
width: 200px; border: 1px solid #000;
margin: 0; margin-right: -208px;
}
}
@media screen and (min-width: 1070px), projection and (min-width: 1070px), tv and (min-width: 1070px) {
#container{margin-left:auto}
}

As you can see, I made the sidenote display as a sidenote for something which could be a window-size on a 1024x768 resolution. I made it display the way I actually intended it to be displayed all along on larger resolutions such as my own. This is a normal small element. A sidenote would be displayed like this in a supporting browser.

The mediaqueries are created to function nicely on a layout similar to this one, but it should be a piece of cake to change this for other layout styles.

In the ideal world, everything would be fine now and the page would display as intended. The ideal world would have a more decent way to markup footnotes, but I'll pretend my small element is that decent way, so ideal applies to a fictional finished CSS3 specification and wide implementation here. Sadly we have not advanced to that level of support yet. Only Opera supports media queries as we speak, so we have to write a Javascript to mimick this behaviour in other browsers, such as Firefox and IE. For now, it might even be the best solution to apply the Javascript to Opera as well, because Opera does not reapply media queries on resize yet (and it does fire the onresize event as every browser does).

The Javascript+CSS method

We have a nice and simple solution now. However, we do need some Javascript. The Javascript I wrote to take care of this problem is as follows (I think the comments explain everything there is to be explained):

if (!window.opera) {
window.onload = sidenotes;
window.onresize = sidenotes;
} function sidenotes() { // declare variables var cont, notes, w_medium, w_large, width; // widths where switching should occur // only values you'd have to change on similar setups w_medium = 900; w_large= 1070;
// assign values to variables cont = document.getElementById('container'); notes = document.getElementsByTagName('small');
// if Gecko (or Opera as you don't need mediaqueries) get the width this way if (window.outerWidth) { width = window.outerWidth; } // otherwise try the IE method else if (document.body.offsetWidth) { width = document.body.offsetWidth; } // if that doesn't work then either the browser will support mediaqueries, or use the float version else { width = 0; }
if (width > w_medium) { if (width > w_large) { cont.style.marginLeft = 'auto'; } else { cont.style.marginLeft = '10px'; } for (var i=0; i<notes.length; i++) {
if (notes[i].className == 'sidenote') {
notes[i].className = 'sidenote sidenote2';
}
}
}
else {
cont.style.marginLeft = 'auto';
for (var i=0; i<notes.length; i++) {
if (notes[i].className == 'sidenote sidenote2') {
notes[i].className = 'sidenote'; } } } }

For this Javascript to work as intended, we would need just one other CSS class:

/* sidenote2 for the Javascript */
.sidenote2 {
float:none;
position: absolute;
right: 0;
width: 200px; border: 1px solid #000;
margin: 0; margin-right: -208px;
}

Now the script will make sure the page will display alike in all major browsers. Or will it? Actually we haven't reached IE compatibility yet, at least the way I did it on this page, but IE7 solves most of the problems in this case. I say most because with IE7 the float doesn't work, which is a good thing however, as it caters against a bug with position:absolute and position:float in IE. Yep, it's tiresome. The size of the script shows how much such semi-behaviour things can make life easier. The script is currently in one way superior to my media query soluction

Concluding

I think this is pretty much the best way to do this until there is a proper way to markup foot- and sidenotes (and long until there is as well probably). IE stands slightly in the dust, but well, that's not of my interest to solve. I would call this degrading gracefully to a less supporting browser, which is what IE is, after all.

Copyright © 2005 Frans de Jonge
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/ ).