[More quick guides]

Printing Tufte with CSS

How to replicate a beloved design

Edward Tufte’s books are beloved for the insight they provide into fascinating topics, and also for their beautiful design. Opening a Tufte book is a revelation – you are presented with thoughtful designs, beautiful spreads, on thick and creamy paper.

The designs in Tufte's books are complex and each page has been carefully laid out by a human being (Tufte himself, I believe). It is impossible for an automatic process to achieve that level of perfection, but we can get fairly close. Prince and CSS can create stunning spreads by using the simple techniques described in this guide.

Our formatter of choice is Prince, a HTML-to-PDF-via-CSS converter which you can download and install on your own computer.

Page size

We start by setting the size of the page, and the width of the margins. This is achieved with some simple CSS code:

html@page {
   size: 220mm 264mm;
   margin: 28mm 22mm 21mm 27mm;
}

We will mostly use millimeters as length units in this guide.

With these settings, the page area is 264mm - 28mm - 21mm = 205mm high. In order to fill the whole page area, we need to choose a line height which avoids leftovers at the bottom of the page. Leftovers are especially problematic in combination with bottom floats, as they will leave a gap above the bottom floats. Fortunately, Tufte's books uses a line height close to 5mm, which is what we will use.

Fonts

Next we set fonts families and sizes:

html @import url(https://css4.pub/fonts/et-book/index.css); 

body {
  font: 11pt/5mm ETBembo, serif;
}

The ETBembo font has been made available by Tufte. We host the font families on the URL listed above, but if you plan to use it beyond experiments, you probably want to download a copy.

Creating a sidenote area

Now we turn to sidenotes, which is a crucial part of Tufte's design. In his books, sidenotes are always on the right side of a page, and the sidenote area is 50mm wide. In this example, we give the sidenote areas a gray background to show where they are:

html@page {
   size: 220mm 264mm;
   margin: 28mm 22mm 21mm 27mm; 

   @rightnote {
      width: 55mm;
      padding-left: 5mm;
      background: #eee;
   }
}

The 5mm padding set on the left side of the sidenote area will ensure some space between the main text and the sidenotes.

Adding content to sidenote area

Tufte uses the sidenote area for bibliographical references, clarifying remarks, and narrow figures. Normal-sized figure are often in the text column, with captions in the sidenote area. Wide figures cover both the text column and the sidenote area.

We will show how to achieve all these designs in this guide, starting with biographical references. These are typically shown close to their anchoring points in the text.

html@page {
   @rightnote {
      width: 55mm;
      padding-left: 5mm;
   }
}

span.note {
   -prince-float: rightnote;
   font: 9.5pt/4mm ETBembo, serif;
   text-indent: 0;
}

<p>... <span class=note>...</span> ...

In this example, the span element is used to hold the sidenote. The aside element is a tempting alternative. However, aside elements cannot appear within p elements and are therefore unsuitable in this example.

Narrow figures

Tufte's books have many figures, of differing widths. Narrow figures are placed in the sidenote area. Their vertical placement varies; in this example the figure is floated to the top of the sidenote area:

htmlfigure.narrow {
   -prince-float: rightnote top;
}

...
<span class=note>E. R. Tufte, <q>The Visual Display of Quantitative Information,</q> Graphics Press (Cheshire, Conn. 1983)</span>

---

<figure class=narrow><img src=img/rhino.png>
<figcaption>F.J. Cole, <q>The History of Albrecht Dürer’s Rhinoceros in Zooological Literature,</q> <em>Science, Medicine, and History: Essays on the Evolution of Scientific Thought and Medical Practice</em> (London, 1953), ed. E. Ashworth Underwood, 337-356.</figcaption>
</figure>

Note that the figure appears below the note in the markup, but due to being floated to the top, it appears above the note.

Normal figures with captions on the side

Normal-sized figures are often shown in the text column, with the caption in the sidenote area:

htmlfigure.normal figcaption {
   -prince-float: sidenote;
}

Wide figures

Wider figures in Tufte's books often appear at the top or bottom of pages. This can easily be expressed in CSS:

htmlfigure.wide {
  -prince-float: wide snap;
}

figure.wide.top {
  -prince-float: wide top;
  padding-bottom: 5mm;
}

figure.wide.top figcaption {
   -prince-float: sidenote top;
}

figure.wide.bottom {
  -prince-float: wide bottom;
}

figure.wide.bottom figcaption {
   -prince-float: sidenote bottom;
}

Baseline alignment

Baseline alignment is a complex topic which has its own guide. In this guide we will achieve baseline alignment by ensuring that:

  1. the height of the figures, plus a sensible distance to the text, is divisible by the line-height of the body font
  2. the height of the page area is divisible by the line-height of the body font
  3. the baseline of the first line of a top-floating caption aligns with the body text
  4. the baseline of the bottom line of a bottom-floating caption aligns with the body text

All but the first of these can be expressed in CSS. But setting the height of figures requires some JavaScript.

In this example, the line-height of the body font is set to 5mm and the dotted pattern indicates the 5mm patterns. Through JavaScript, each figure is set to n*5mm+3mm. The red areas is the 2mm padding which is added by CSS, to set a suitable distance between the figure and the caption. In sum, this operation ensures that the figure with padding is a multiple of the line-height.

html<script type="text/javascript" src="../charms.js"></script>
<body onload="height('img', '5mm', '3mm')">

Baseline alignment without guiding colors

This is the same example as the previous, just with the guiding patterns removed:

html<script type="text/javascript" src="../charms.js"></script>
<body onload="height('img', '5mm', '3mm')">

Screen-friendly version

Common browsers do not support sidenotes, but setting negative margins allow us to simulate the effect so that the same HTML code can be used both for screen and print. This HTML code in this example is unchanged from the previous example, but a screen style sheet has been added. Therefore, when you click on the html link on the right side, you will see a decenct-looking presentation.

html<script type="text/javascript" src="../charms.js"></script>
<body onload="height('img', '5mm', '3mm')">

Adding sidenote markers

Tufte numbers sidenotes, much like footnotes are numbered.

html.note:before, .snc:after {
   content: counter(sn) " ";
   font-size: 0.8em;
   line-height: 0;
   vertical-align: super;
}

.note {
   counter-increment: sn;
}
...
<script type="text/javascript" src="../charms.js"></script>
<body onload="addSidenoteMarks('.note', 'snc');">

Complete books

This guide only describes how to create one spread, not complete books. Also, running headers and footers are omitted. For an example on how to create a complete book, you can find the HTML code and the resulting PDF.

2023-03-17 Håkon Wium Lie