Wednesday, May 14, 2014

Using images as initial drop caps

Decorative initials are often sold as images, whether bitmap or vector, and whether as a set (such as one for each letter from A through Z to Æ) or singly. It’s common for alphabets to be incomplete, partly because J and W came relatively recently to our alphabet and partly because you often only get letters that occurred at the start of a chapter in the book for which they were designed.

Images lack some important information that is available for glyphs in a font. Fonts have information about where the baseline is to be found, and sometimes also the x-height and cap-height, and the character advance which is generally different from the bounding box. Images only have the bounding box: the size of the image. But we need that other information in order to position a drop cap correctly.

I’ll use an example from the GNU/Linux™ programmers’ manual to illustrate what I mean. Here, the blue and red “L” is a single image (a JPEG image in this case, from my own Web site at of course).

To make clearer exactly what’s going on I drew some lines:

Here, the image actually goes from just inside the left edge to line B; I darkened the image slightly so you could see the rectangle. Vertically it goes from line 1 at the top down to line 4 at the bottom. The image is positioned so that the top of the red “L” lines up exactly with the top of the first line of capital letters (line 2). The baseline of the “L” is harder to see, but lines up exactly with the baseline of the fourth line of text, (the line marked 3).

Because the first word is LSEEK, the rest of the first line (SEEK) is set close against the L. The remaining lines are flush against the edge of the image (line B) in this example. I’m not yet ready to describe non-rectangular images.

To get this right, we need to know the distance from line 1 to line 2, so that we can float the image backwards in the text until the top of the “L” lines up (I am assuming the reference to the image occurs just before the SEEK, in that paragraph, and not earlier in the page). We also need to know the position of line 3 so we can align the baseline to the text. In general, if you can't align everything, aligning the baselines is most important, although in this particular case you could reasonably argue that the curvy flourish of the “L” gives extra freedom. Don’t succumb to temptation: do it right.

There are actually three ways to set this initial and get everything aligned.

  1. Choose the size of the main body text and the line spacing so that you get an even number of lines (see below for the actual calculation);
  2. Scale the image so that it fits—this would work best for an SVG image rather than the JPEG that I have;
  3. Allow the image to rise above the start of the paragraph (least desirable but easiest to do).
The formula for the text size is that you want three times the full baseline-to-baseline distance plus the cap height of the text font to equal the height of the letter (not the height of the whole image, of course, which is almost never the same thing). Since in CSS you can never be certain which fonts will be used to display a document for any given user and browser/user agent, you cannot get this formula right for the Web. You can get it right for print, if you are printing your own document, of course.

Another difficulty is that CSS does not currently have a way to force lines to have their baselines glued to an invisible grid that’s a multiple of a line height (or a multiple of 0.5LH units, or ⅓rd for some designs). So the superscripted “e” on the first line may mess everything up.

The imaginative reader will also be wondering what should happen when the paragraph with the decorative initial should fall at the start of a page instead of the middle, so that there is no room for the blue flourishes above it. it would be nice to be able to supply alternate images for that case, but I am going to ignore it here, because it would be a separate mechanism entirely.

Scaling the image to fit also requires the same formula, but now instead of the cap height and line spacing being variable we have the image height being variable and the other quantities fixed.

As with drop caps made from fonts, it is always visible baselines that align, not invisible CSS line boxes. But with images, we need a way to mark the baseline, the indent (which we probably already have with text-indent) and the topmost (cap-height) alignment point, and to give a kern amount for the first line in the event that the letter forms art of a word.


Unknown said...

You've clearly put in the thought behind this Liam... Perhaps you could suggest some CSS which might produce this? I simply can't see it at the moment?

Liam Quin said...

There isn’t any CSS to do this yet, which is why people get it so badly wrong on the Web.

The CSS Working Group is meeting this coming week and it’s on the agenda. I don’t know what the outcome will be, of course. I took the work we did in the XSL-FO (XPPL) group as a starting point.

Unknown said...

Keep us posted please. I'm finding this very interesting.