Sunday, April 13, 2014

Formatting drop caps with CSS

These notes are for a proposal for ways to handle drop caps in CSS; don’t try to use them because this is only a proposal, not a description of how things work.

A drop cap, or dropped capital, is an initial letter, usually at the start of a section of text, that uses a larger type size than the main text that follows. Functionally, a drop cap signifies the start of a section that’s more important than one without a drop cap.

As with much of typography, a drop cap needs to appear to have been put there on purpose in order to make a strong, assertive statement and not raise doubts in the mind of the reader. For a drop cap to work it must align properly.

There are generally five alignment points for a drop cap. The first, and most obvious, is that the feet of the initial must sit on a baseline of text. For a five-line drop cap, the initial letter sits on the fifth baseline. It should be exact, not approximate.

Here’s a 1740s example that’s approximate because you could only get metal type in fixed sizes. I’ve used it because it shows how bad it looks when the initial doesn’t line up properly:

Example of drop cap showing alignment, to be explained in the text.
Figure 1. Mediocre example from Thoms Hearne’s edition of Leland’s Itinerary; Oxford, 1740.
In this example the base of the F should align with the words South side of the, and it almost does. The top of the F should align with the top of ROM Cambridge, and our 1745 compositor loses marks here. It’s common to use small caps for the first word or two after a drop cap but here full capitals have been used, leading to a cluttered appearance.

Finally, the left edge of the F should align with the left margin. You can see the serif on the foot does align with nery and tendune, and although an optical alignment would put the serfs slightly into the left margin, this is perfectly adequate.

Figure 2 shows a modern reproduction, retaining the full capitals in the first word but improving the alignment. It lost a little of its quaint olde-worlde charm, but by lining up properly it’s less distracting. It’d be even less distracting as a three-line drop cap instead of a five line one, but that’s another matter.

Example of drop cap showing alignment, to be explained in the text.
Figure 2 - Modern version of Figure 1.

Earlier I said that there were five alignment points for a drop cap. I’ve talked about (1) how the baseline of the drop cap shares a common baseline with the nth line of text, and (2) how the top of the drop cap aligns with the top of the first line of text. I’ve mentioned that (3) the “before” edge (the left side in figures 1 and 2) of the drop cap lines up with the margin, that is, with the edge of the text, either optically or (as in the figures) mechanically. There’s one more alignment point to look at before we move to describing the drop caps in more detail, and that’s the space between the initial and the first line of text.

In Figures 1 and 2, the first line of text begins, “From Cambridge to…” We have a huge initial F followed by letter-spaced capital R, O and M in from. The R is close to the F, closer than the gap between the drop cap F and the text on subsequent lines. This is done to show that the initial forms part of a word, and joins on to the rom to make from. If instead the text had been, say, “I walked from Cambridge to…” then we’d see a large initial I and the w of walked would line up with the start of each line below. So this is the fourth alignment point.

The fifth and final alignment point is when an initial is raised, so that it goes above the first line of text. We’ll talk about raised initials later, after we’ve dealt with the simplest case of a drop cap. Note also that although the descriptions here use a Latin alphabet, drop caps are also used with other writing systems and generally work in the same way. This is no surprise because much of graphic design and typography is a reflection of human vision and perception. I’ve also used terms like height and left and top, and for right-to-left or vertical scripts you’ll have to rotate accordingly.

Font sizes

In our example, the lines of text have an even baseline spacing. It might seem that you could take the initial font size and multiply by five to get a five-line drop cap, but that doesn’t actually work in practice. One reason is that we have to align with the cap height on the first line, not the top of the CSS line box.  Another is that font size actually refers to an invisible box around the characters that corresponds to the piece of metal anciently used for pieces of type. The font has to leave room above ascenders for diacritical marks (accents), and below the bottom of the descenders so that the ascenders and descenders don’t bump into each other. For the modern example in Figure 2 I used 12pt Adobe Caslon Pro; the initial F is Caslon 540 at 81.35pt.

Calculating the correct size for a drop cap can take a binary search algorithm with some font programming interfaces, but essentially we need the F to be sized such that its cap height (or at least the actual height of the F glyph) is equal to four times the line height (that is, four times the distance between successive baselines of text) plus the cap height of the text on the first line. Since different fonts have different ratios of cap height to font size this size has to be worked out based on the actual computed font in use for rendering the F and the text.

If you use downloadable fonts (e.g. woff format) you can work out the right size for a drop cap in advance, but if the user has disabled font downloading or is on a browser that doesn’t support it, the fallback looks pretty awful. Often worse than the example in figure 1, because neither the top of the initial nor the baseline will align properly in most cases. But we can try:

<!DOCTYPE html>
<html>
  <head>
    <title>Hearne</title>
    <style type="text/css">
      body {
        font-family: "Adobe Caslon Pro";
        font-size: 12pt;
        line-height: 1em;
        color: black;
        background: white;
      }
      p span.dc {
        font-size: 81.35pt;
        line-height: 1em;
        display: block;
        float: left;
        font-family: "Caslon 540";
        margin-top: -13pt;
        margin-bottom: -12pt;
        margin-right: 12pt;
        margin-left: -3pt;
      }
      p span.firstword {
        text-transform: uppercase;
        letter-spacing: 0.5em;
        margin-left: -12pt;
      }
    </style>
  </head>
  <body>
    <p><span class="dc">F</span><span class="firstword">rom</span> <i>Cambridge</i> to <i>Elteſle</i> Village by Champeyne counterey 8. Miles. At <i>Elteſle</i> was sumtyme
      a Nunnery wher <i>Pandonia</i> the <i>Scottiſh</i> Virgine was
      buried.  and there is a Well of her name yn the
      South ſıde of the Quire.  I hard that when this Nunnery was destroyid a new was made at <i>Hinchingbroke</i> by <i>Huntendune</i></p>
  </body>
</html>

Figure 3 shows what we might get:
Figure 3: try.html in Firefox 29.


It worked, but to get it right I had to set margin properties to numbers found by trial and error, and you’d need a browser CSS reset to make sure user agent defaults didn’t get in the way unexpectedly. So far this is all pretty straight forward although the trial and error part is tedious and error-prone.

What about accessibility? I had to set the F to have display block, but we really want a text reader to pronounce the first word as from and not as capital eff capital rrr capital oh capital emmm. Similarly we want Web crawlers such as the various Google bots to index the page correctly. A problem with this solution is that it’s too low-level, and doesn’t really say what’s going on. We could work around the text problem but there’s a harder problem to solve.

Suppose the user doesn’t have Adobe Caslon Pro. We could add a fallback font, but then all the numbers have to change. Or suppose the actual character to be used isn’t known in advance, and it turns out that the glyph for it comes from a different font. In that case the numbers need to change. The -3pt margin left is to allow for the side-bearing of the F, the white space like a margin that’s on each side of every letter so that they don’t bang into each other. But different shaped letters have different side-bearings.

Worse, many designers use decorative initials for drop caps. These are sometimes in a separate font but more often are sold (or made available) as individual images. So now we need to position the image correctly, but also have things work right if the image isn’t used.

 Proposed CSS Treatment


All this background is really to explain that the only reliable way to have drop caps work is to tell the CSS engine, the renderer, that you want a drop cap.

      p span.dc {
        initial-cap-lines: 5;
        initial-cap-kern-lines: 1;
        font-family: "Caslon 540";
      }

Don’t get too excited: these are proposed CSS properties, not current ones. The idea is that you can specify a number of lines or a distance for initial-cap-lines. That’s important because if the line spacing is uneven, perhaps because of a superscript, we want to give the renderer the option of aligning to the nth actual line or to where the nth line would have been if the line spacing had been even. The second of those is a compromise needed because of corner cases, such as when there’s a superscript right at the end of the text that’s indented by the drop cap: making the drop cap larger because of the extended line box at the end makes the superscript wrap onto the next line and suddenly it’s no longer needed. A sophisticated formatter can usually avoid that case by changing the line-breaking earlier in the paragraph, but that’s not always feasible in the case of editable content. So we let the user say, five lines please, and we let a formatter, such as a Web browser, fail in some of the same edge cases where other approaches also fail. But by saying 5 lines instead of a length the browser can do the right thing in a lot more cases.

The initial-cap-kern-lines property lets us say how many lines of text to try and move closer to the initial. Probably the only sensible choices are none, one, one-unless-there-is-a-space, and all, so maybe it should just be a keyword. again this is an optional property: a formatter might not known enough about character outlines to get this right.

We need to return to the other alignment points. Sometimes initials protrude into the left margin or stick up as raised initials. I’ve used this Greek example (Fgure 4) before:
Figure 4. Greek initial cap.
In Figure 4 there is a Greek text with a decorative initial capital Alpha (formally, a foliated initial) at the start. I’ve added lines in the figure to show the baseline alignment. You can’t tell from the figure that the apex of the alpha aligns with the cap height on the first line, but you can tell that it has vines and leaves swirling off into outer space above the first line and into the left margin. There’s also a decoration underneath it, but we’re going to ignore that for a moment.

An initial-cap-lines-before property (maybe someone can find a better name) could be used to move the alignment point down, so that the top of the first line of text lines up with a point two lines (say) from the top of the initial.

We can put the initial into the left margin with margin-left but we can’t put the whole initial, nor half of it, into the margin that way, as we don’t know the width in advance. An initial-cap-indent property could be used to specify the indent, with a percentage taken as a percentage of the width (in the inline-text direction) of the drop cap character text.

Some corner Cases

A drop cap is not always the first thing on a line. In some languages an open quote or even a letter might precede the initial, at regular size or larger than usual but not at drop cap sizes. Figure 5 gives an example from a Dutch book.

Figure 5. Drop Cap preceded by a letter.
Some people use multiple letters, or even a whole word, as drop caps. There’s no accounting for taste, but technically there is no difficulty.

Issues

What sort of markup should be used if there’s an image for a drop cap but we want fallback to a 3-line drop cap?

If the image is in SVG can we somehow scale to the right alignment points?

Why did I say there were five alignment points? They are
  1. The baseline of the nth text line aligned with the baseline of the initial;
  2. The top of the initial (cap height) aligned with the cap-height, or small-cap height, of the first line of text;
  3. The first line of text kerned close to the initial if there is no word separator (space) in the input;
  4. The left (“before”) edge of the initial and its alignment with the margin;
  5. The top of the initial if it protrudes, so that the alignment point is not the cap height of the initial; this is really a more general case of (3).
But I have not added a sixth point for space after the initial. There needs to be a way to specify that, so that’s an issue.