Difficulty: ★☆☆ (easy)
Keywords: initials, drop caps, floats

Problem

You need a “drop cap”, or Initial, which is a “a letter at the beginning of a work, a chapter, or a paragraph that is larger than the rest of the text.”

Solution

Typographically, you have different options to place initials:

  • on the same baseline as the first line of text,

  • as floats, embedded between two or more lines,

  • besides the left margin of the text block without indentation.

Additionally you can design your initials as graphics, but we will come to this later.

Place Initials on the Same Baseline

This is the easiest method to implement. The stylesheet normalizes the text node of the first paragraph, extract the first character and wrap it between an fo:inline element with font size, family, and weight:

Example 4.2. initials-baseline.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:param name="drop.caps.size">20pt</xsl:param>
  <xsl:param name="drop.caps.font-family" select="$body.font.family"/>
  <xsl:param name="drop.caps.font-weight">bold</xsl:param>
  
  <xsl:template name="create.initial">
    <xsl:param name="initial" select="substring(normalize-space(.),1,1)"/>
    <fo:inline>
      <fo:inline font-size="{$drop.caps.size}"
        font-weight="{$drop.caps.font-weight}"
        font-family="{$drop.caps.font-family}">
        <xsl:copy-of select="$initial"/>
      </fo:inline>
      <xsl:value-of select="substring(normalize-space(.), 2)"/>
    </fo:inline>
  </xsl:template>
</xsl:stylesheet>

To use it, include it into your customization layer. It is usually called in text nodes like the first paragraph from a section which parent is an article:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet 
[
 <!ENTITY db "https://cdn.docbook.org/release/xsl/current"> 
]>
<xsl:stylesheet version="1.0"
  xmlns:d="http://docbook.org/ns/docbook"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:import href="&db;/fo/docbook.xsl"/>
  <xsl:include href="initials-baseline.xsl"/>
  
  <xsl:template match="d:article/d:section/d:para[1]/text()">
    <xsl:call-template name="create.initial"/>
  </xsl:template>
</xsl:stylesheet>

It is easy to extend it to chapters, you just have to copy the template and correct the content in the match attribute to:

<xsl:template match="d:chapter/d:section/d:para[1]/text()">

Implement Initials as Floats

TBD

Place Initials in Left Margin

TBD

Discussion

The solution described in the section called “Place Initials on the Same Baseline” is in most cases sufficient. However, if the first character is not a letter, any character is incorrectly made an initial.

See Also

Find information about the property line-height in Section 4.4, “Influencing the Leading”.


Project@GitHubIssue#9