Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

Monday, December 7, 2020

CSS Within XSLT - a way to simplify simple HTML generation from XSLT

It can be a challenge to keep CSS files up to date as you change XSLT transformations to produce different HTML output. You've got to remember what you changed and then work out which CSS rules are affected and update them. Removing out-of-date rules is important, and can even affect your site’s ranking in search results, but it’s hard to do and requires attention to detail.

Recently I’ve been taking a different approach and I’m finding it much more productive.

Saturday, October 6, 2018

Layered Fonts with CSS and JavaScript

The established ways of using layered fonts on the Web all have problems, so I tried to come up with something new.

Layered fonts are typefaces designed to be overprinted, so that you get a colour effect. Here's an example from Tom Chalky’s Rivina font family:





If you look closely at the word “Chapter” you can see the letters are blue with a greyish outline. I've magnified some of it in the inset circle. The way this works is that there are two separate fonts: TC Outline just draws the outer edges of the font and TC Fill draws the inside of the letters; the text is repeated at the same location, once in each font, to create the effect.

More complex fonts can include many more “layers” than the two I’ve used here (and in fact Rivina includes more variants than I’ve shown).

This technique was invented in the 19th century and has been used in every medium to make a simple coloured printing of headlines.

To use fonts like this on the Web and not be ashamed of ourselves we need: ...

Thursday, December 3, 2015

Declarative Index Proposal for Printing with CSS

This proposal is about formatting an index with HTML and CSS. It’s something you can’t do today in a standard, cross-implementation way.

The part you can’t do today is getting the lists of page numbers right. The same problem occurs in an index and in cross references. There are vendor extensions to do it, but they are not compatible, so it’s a good candidate for standardization.

A back of the book index looks like this:


Sunday, August 17, 2014

Back-of-the-book Indexes and CSS

An index in the context of printed books is a list of topics with associated page numbers, usually printed at or near the end of the book.

The plural is indexes, unlike the mathematical indices, which are different beasts that happen to share the same singular form, index.

To make an index for a digital document, you:
  1. Mark the targets, the topics, in the main book itself;
  2. Extract the list of topics, or index headings as they are called, and sort them;
  3. For each topic, collect the list of appropriate page numbers;
  4. Collapse runs of adjacent page numbers into ranges.
All of this can easily be done declaratively. There are some minor complications to resolve, but they are not too hard:
  1. Sorting multilingual headings, symbols, and other items;
  2. Multi-level indexes;
  3. Mixtures of references of differing types;
  4. References to footnotes;
  5. Balanced column formatting.
 

Sorting

Books might well have multiple scripts in use, such as Latin for English and Spanish and Devanagari for Hindi. It may be necessary to use different collations for different parts of the index, for example to get an index of Spanish names to sort names starting with Ch properly without affecting the index of French names on the next page. It may be appropriate to provide a sort key for an individual index heading to get it to go where you (as author) want it.

Even a moderate sized book can have hundreds or thousands of index entries, so sorting them obviously should be done automatically.  However, it is possible to do that outside of CSS, for example with JavaScript or XSLT, before formatting. A minimal proposal for supporting indexes in CSS therefore does not need to address sorting the index.

Multi-level indexes

It’s not uncommon to see sub-topics collated together in an index:
    Socks, black, 28, 73; argyle, 24-56, 72; white: 24

This is done partly to save space in the index, partly to make using the index more efficient (everything to do with socks is in one place, instead of under A for argyle,, B for black and so forth) and partly to avoid ugly and potentially confusing repetition of the main head (socks) for each sub-entry.

The consequence for software is just that you need a multi-level sort.

As with sorting the index itself, collation and sorting of sub-entries can  be done before formatting the document and doesn’t need to be specified with CSS. We only need to bother ourselves about the page numbers, which must of course be supplied by the formatter.

Mixtures of references of differing types

It’s common to indicate in an index more than just the page number but also what the reader might find there: a discussion, a definition of a term, a figure, a table, a mention in passing. Note that the actual index heading might not appear in the text; a discussion of argyle socks might not mention the word “sock” but only talk about the pattern, or perhaps use the word “stocking;” this is part of why a well-crafted index can be more valuable than automated searching for some applications.

The usual ways to distinguish the different types of reference are to use bold page numbers for definitions, italic for figures, and perhaps to prefix the page number with a symbol such as an asterisk (*) or dagger (†) for a table.

This means that if you have a figure that occurs in the middle of a discussion it’ll be listed separately:
    Socks, argyle, 24-28, 26, 72

References to footnotes and other page areas

A reference to a footnote usually has an annotation such as 46 note 1 so that the reader has warning both of where to look on the page and that the reference might not be part of the main discussion. If there are references to multiple footnotes on the same page they could be listed,
    Socks, argyle, 24-28, 26, 72 note 1, note 3.

Other areas that might have specific annotations in an index include sidebars, examples, tables, side-notes (marginalia) and other secondary content. Books with large, dense pages such as the Encyclopædia Britannica might divide the page into areas and have a reference like 46C to mean the bottom left quadrant of page 46 but these are specialized books, often produced with highly customized software.


Balanced Column Formatting

I’ll mention this for completeness, because the index-specific processing is all about the references. Indexes are usually printed in relatively narrow columns, three or more to a page. On the last page of the index the columns will probably all be balanced so they are the same height (give or take one or two lines in the last column).

It can be important with the back matter in a book to remember that the book must usually be a multiple of 16, 32 or 64 pages to be printed economically by folding large sheets of paper. So if you end up with two lines of index on the last page you’ll want to set a shorter page if that avoids having 63 blank pages after it!


Formatting with CSS


CSS doesn’t yet support index generation, but XSL-FO extended CSS 2.1 to add properties for indexes, and this was implemented and today is widely used in production. So maybe we can do something similar.

You can also refer to the XSL-FO 2.0 draft for a much more detailed explanation that I am going to give; we don’t need as much because CSS already has ways to do most of what we need. I think there may also be a mistake in the summary of generated page numbers as page 14 doesn’t appear anywhere; if so, sorry.

Let’s suppose for now that we have an HTML (or XHTML) document containing a sorted index ready to format. it might have markup like this, to generate
    Socks, argyle, 24-28, 26, 72

<li class="index-entry">
  <p>
    <span class="head">Socks</span>
    <span class="subhead">argyle</span>
    <a href="#ie41" class="ie"></a>

    <a href="#ie42" class="ie"></a>
    <a href="#ie46" class="ie"></a>
    <a href="#ie50" class="ie"></a>
    <a href="#fig17" class="ie figure-ref"></a>
    <a href="#ie51" class="ie"></a>
    <a href="#ie52" class="ie"></a>
    <a href="#ie53" class="ie"></a>
    <a href="#ie141" class="ie"></a>
    <a href="#ie142" class="ie"></a>
  </p>
</li>

We don’t know the page numbers in advance so we can’t put them there. They’ll be supplied by the content property.

Suppose when the document is formatted the targets referred to end up being on pages 24, 24, 25, 26, 26, 26 (the figure), 26, 27, 28, 72 and 72.

The formatter will need to process this list:
  1. separate out the figure reference
  2. collapse duplicate numbers in the list
  3. collapse ranges into a start and end with a separator
  4. merge the separate streams (here, references to text and to figures) by sorting on the first number in each range.
A complication is that the page number used for sorting will presumably be the page built-in variable, but the value printed will be as it might appear on the page running header or footer, so that an introduction page might get roman numerals (Socks, white: xxiii) and an appendix might get a preceding letter, known as a folio prefix, such as B for Appendix B (Socks, internet proxy: B-42). This is the same as for general cross-references within a book, of course.

When eliminating duplicates, the value of the index-merge property determines whether a sequence of three or more consecutive page numbers are merged together to form a range, or if they are kept separate.

A second complication is that if there were ranges in the example instead of just individual references, the formatter would typically expand the ranges into a list of individual pages first (in practice this will be a short list) between steps one and two in the process, because that simplifies the process of eliminating duplicates.

In addition, items with different index-class values are normally kept separate, but a property index-merge-differing-classes can be set so that the figure reference in the example would vanish, as it’s contained with the 24-28 page range.

After handling page ranges the index entries are formatted normally, with the content property and :before and :after being available to support the various page number formats, and to allow marking index entries to colour plates (say) in [square brackets], just as for a normal cross-reference. However, the number of “a” elements/nodes may in general  be fewer than in the original document before index processing. It can never be more: references within a range that were expanded to simplify processing in an implementation do not result in new elements being created.

Issue: should the transformation from original list to sorted, merged list use the shadow DOM?

Issue: how best to supply the comma, en dash or “ and ” between entries? XSL-FO just inserts a text node with no standard way to change the en dash or comma and space.


Properties (proposed)


index-class: a user-defined “ASCII-lower-case” string; entries with different index class values do not by default get merged together, so that you can keep figure references even when they fall within a range of text pages, of keep a definition even if it, too, falls within, say, a range of figures.

index-item (none, begin, end, span, point): set this on the “a” element. It does not inherit. “span” means that all of the pages generated by the target element are added to the index; otherwise the page on which the element starts is used. The begin and end values are used in pairs to mark index ranges and point is used for a stand-alone page reference. None turns off index processing on the given element.

index-list: Use index-list for the containing element to indicate that its children are to be processed as index citations; this would be used on the “p” element in the sample markup above. Values are none (don’t do index processing), no-merge, same-index-class, all). A value of same-index-class means page ranges are merged only when they have the same associated index-class value. A value of  between-classes means index-class values are ignored for the purpose of merging. A value of no-merge enables index processing but not merging of adjacent pages into a range. In all cases page numbers that are explicitly marked as being a range using index-item begin and end are kept as a range.

Issue: is this enough? I’ve proposed merging XSL-FO merge-pages-across-index-key-references and merge-ranges-across-index-key-references into the values of index-list but I have lost the ability to merge between index classes and not within a class; I think that combination never made sense. The page-number-prefix and suffix can be done with before/after.

Other items

Indexes might contain cross-references such as “Stockings: see under socks” which do not need special formatting. One might make the text be a link, of course.

Column balancing is outside the scope of index processing.

Formatters are not expected to support index entries that point back into the index itself.

If you reset the global page counter, the index facility proposed here will give you strange results.

Comments?



Saturday, May 17, 2014

Drop Caps: Other Writing Systems, Other Styles


In this entry I’ll start with some more Latin script examples in order to illustrate some principles, and then discuss some variants for other writing systems. This entry is very incomplete and needs a lot more research; I'm publishing it so people can help.


First, a cameo initial; that is, where the letter has a solid background:

The picture shows an SGML viewer I wrote a long time ago, displaying part of Thomas More’s Natural History. The initial is white on a dark reddish rectangular background and because the background is such a strong design element it is that background that aligns with the cap height and with the baseline, not the actual capital “I” inside it. If you are working with a font for decorative initials this is what will happen automatically. This example aligns with the small caps height, by the way; that would work if the entire first line, or at least the first two words had been set in small caps, but with just the “T” in “IT” in small caps the result is  somewhat unsatisfactory.

I am showing this example now because it gives a way of making your own decorative initial: you can draw a rectangle and put any letter inside it, and as long as the letter is well within the rectangle and as long as there is strong contrast you can get away with it. Note that you cannot do this with an img element and float, in general, as you don’t know what font size the user will have for the text and hence you don’t know how big to make your rectangle. With css calc() you could maybe say it is 2LH + 1CH, where CH is the cap height of the current font, but I don’t know as we have that unit yet, and LH (line height) is probably also not supported.

Next an example to show the idea of treating a “glyph” from a font as an image and then running the text around it:
This “A” is from an article by Allan Haley in U&lc Type Selection (London, 1992). It’s hard to see that the top of the A aligns with the cap height in the first line as there are no caps; the feet sit happily on the sixth baseline from the top, and the serif at bottom left protrudes a little further into the margin than would be normal, in order to make an effect. But the most important thing here is that the text abuts the edge of the A as closely as possible.

This is not the usual way to do a drop cap, partly because it wasn’t possible with earlier typesetting systems: with metal type and woodcut or metal initials this level of kerning involved filing (or kerfing) not only the initial but also the individial sorts, or pieces of type, for the first character on each line, and doing that with an apostrophe would be awfully hard. With film photosetters all the way to early laser printers the glyph outline shapes were not available to the renderer - only the character widths.

Today its possible to do this sort of work automatically, but the way to do it in CSS would probably be to be able to derive an image from a font glyph, and then use a runaround. The alignment points of the image would have to be set just as for a regular bitmap or SVG image used as a drop cap.

Let’s look at some more Western examples before moving on; I’ll use examples from the same article.


The raised initial “r” here is thoroughly modern and very conscious: people reading the text will notice that letter. It’s again treated as an image, so that the text can be run up next to the letter. One more of these, showing a different alignment point. I think this does not need to be in scope for CSS, because you would probably have to set the whole paragraph so carefully that you would end up using SVG, or an image.
Notice the top bar of the “f” lining up with the heading to the left as well as to the x-height on the first line of text. This is not really a drop cap or initial letter at all.

You can see the rest of that article at uandlc.com starting at page 18. There are quite a few more examples.

Now that we have seen some more complex Western examples, let’s consider other writing systems, starting with Arabic.  The initial capital does not work well with traditional Arabic calligraphy, because the individual letters are joined together and you can’t join a large thick letter to a small thin one without something looking really odd. The examples I have seen are mostly modern. Some use a modern sans-serif Arabic font, and it seems one approach is to draw the first letter large in a square, rather as I did with the cameo initial at the start of this blog entry, and to continue with a joiner such as “ـ” and the rest of the word small. If the square (whether cameo/reversed or not) is not used, the sane serif font seems to work best. A couple of examples (with kind thanks to Roozbeh Pournader and Shervin Afshar) can be found here and here. Typesetters and designers are still experimenting with alignment and positioning and style, as the initial cap seems relatively new. A larger initial word also occurs in Arabic, and in the examples I have seen so far is simply raised, like the raised initial “r” above.

The Arabic tradition of text as playful calligraphy suggests techniques like the “f” above will be common, and indeed they are common in calligraphy: I have seen a great many examples from Iran and Iraq especially. But they are not so common in typeset work, possibly because it quickly becomes too difficult. There are a couple of artistic calligraphic examples here and here by ibrahim abu touq of Jordan, or here is one by Malik Anas Al-Rajab in Iraq. You can’t do anything that wild with OpenType (although there are some sophisticated attempts) and the boundary between typography and calligraphy is fluid in the Arabic world, but the typography is only slowly starting to catch up with the calligraphy. The engines simply couldn’t take it.

See also this Google Group discussion.

For Chinese and Japanese I have seen examples with the first ideogram, or the first few characters, set in a box with a line round it, rather like some of the Arabic script examples. In this case, the box aligns with the character grid used for the text. However, it seems uncommon. A copy of GQ Magazine from Japan has nothing like a drop cap anywhere that I can see. I’d love to know more. The examples I have seen of a two-line drop cap in Japanese may just be a function of someone using InDesign or Microsoft Word (or JustSystems?) which supports the feature in some way. What about Korean? Mongolian?

For Indic languages such as Hindi (using the Devanagari writing system) the principal seems to be so use the top and bottom extent of the letter, just like an “A" in the simpler Latin script styles. Devanagari is interesting because the nominal baseline is actually not at the bottom of the characters, and the writing system does not really have the same alignment points as the Latin and Greek scripts. As with Hebrew (see below) it’s not just a single character that is made larger. For Hindi it’s generally a syllable, so that in स्थिति its the स्थि that is enlarged. I do not have information about alignment: does the result share a common “clothes line” baseline?

I do not yet have information on Indic scripts other than Devanagari (the example here came from Richard Ishida of W3C) but I have seen printed samples in other scripts. I had hoped that the W3C Indic language Requirements Document would clarify this, but the document didn’t really get far enough yet.

For languages like Slavonic and Vietnamese using Latin characters with lots of diacritical marks you end up having to decide what to do with accents. Accents, or diacritical marks, are entirely ignored when sizing and positioning an initial cap, but are taken into account when you have to avoid other things (such as text above or below) bumping into the letter. In practice this means that extra marks below a letter will probably cause an extra line of two of the main text to be indented, but the baseline of the main character aligns with the baseline of the nth line of text, and the cap height of the main character aligns with the cap height of the main text on the first line, even if that pushes accents up above the start of the text. This means that a 5-line drop cap (say) will use the same font size for the initial throughout a publication (assuming the body font and line spacing are the same), regardless of accents, and that’s what you want, following the graphic design principles of Similarity and Repetition.

This leads me round to Hebrew, where the entire first word of a paragraph is sometimes set larger making a “drop word.” Again I do not have information on alignment, especially of cantillation marks (John Hudson maybe?)

Cyrillic drop caps seem to work the same as Latin ones.

In almost all the cases I have seen the basic principle is the same: you line up the base character (or syllable or word) with the top of the base characters on the first line and the baseline, or bottom of the base characters (e.g. for Devanagari) on the bottom. For vertical scripts top and bottom are obviously rotated appropriately.




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 http://www.fromoldbooks.org 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.



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.





Web History and SoftQuad HoTMetaL

 Years ago, starting in 1989, i worked at SoftQuad Inc. in Toronto. I got there because SoftQuad sold a text formatter based on troff (sqtr...