Side-by-side formatting

Displaying text items side by side with a hanging indent is a common format that has many applications. Here are some example design ideas:

All of these designs can be achieved using the XSL-FO fo:list-block element. It formats like a two-column table. One example of its current use is for variablelist, where it displays each term element in a varlistentry next to its listitem body content. The same kind of side-by-side formatting can be done for a single pair rather than a sequence of pairs. The only restriction is that there be only two items side-by-side. Any more than that and you will need to use a table.

The following is an example customization that puts a section number at the left margin next to its indented section title.

Example 13.15. Format section titles with fo:list-block

<xsl:param name="body.start.indent">30mm</xsl:param> 1

<xsl:template name="section.heading"> 2
  <xsl:param name="level" select="1"/>
  <xsl:param name="marker" select="1"/>
  <xsl:param name="title"/>
  <xsl:param name="marker.title"/>

  <xsl:variable name="title.block"> 3
    <fo:list-block start-indent="0mm"
            provisional-distance-between-starts="{$body.start.indent}" 4
            provisional-label-separation="5mm">
      <fo:list-item> 5
        <fo:list-item-label end-indent="label-end()" text-align="start"> 6
          <fo:block>
            <xsl:apply-templates select="parent::*" mode="label.markup"/> 7
          </fo:block>
        </fo:list-item-label>
        <fo:list-item-body start-indent="body-start()" text-align="start"> 8
          <fo:block>
            <xsl:apply-templates select="parent::*" mode="title.markup"/> 9
          </fo:block>
        </fo:list-item-body>
      </fo:list-item>
    </fo:list-block>
  </xsl:variable>

  <fo:block xsl:use-attribute-sets="section.title.properties">
    <xsl:if test="$marker != 0">
      <fo:marker marker-class-name="section.head.marker">
        <xsl:copy-of select="$marker.title"/>
      </fo:marker>
    </xsl:if>

    <xsl:choose>
      <xsl:when test="$level=1">
        <fo:block xsl:use-attribute-sets="section.title.level1.properties">
          <xsl:copy-of select="$title.block"/> 10
        </fo:block>
      </xsl:when>
      ...
    </xsl:choose>
  </fo:block>
</xsl:template>

1

Sets a body.start.indent to indent all body text from the left margin. In this design, the section number will be out to the left margin.

2

Customize the template named section.heading, which formats the title with correct properties for each section level. It works for both section and the sect1, sect2 type of elements. It usually formats the value of its title parameter, but this customization will generate the title in a formatted block.

3

Define a variable named title.block that will be used in place of the $title parameter passed into this template. The local variable will hold the fo:list-block until it is output at a given section level.

4

The fo:list-block element has three properties:

  • The start-indent is set to zero so the left edge of the fo:list-block starts at the left margin, so the section number can appear there.

  • The provisional-distance-between-starts is set to the width of the indent of the list-block. In this case, it indents to a value equal to the body indent. Then the title will line up with the body text. You can set the indent to any value you want.

  • The provisional-label-separation establishes the minimum space between the end of the left text and the beginning of the right text.

5

This list block contains a single fo:list-item element, which contains the list item label and list item body.

6

The fo:list-item-label element contains the left text. Its end-indent property uses a special XSL-FO label-end() function to compute the indent of the right side of the block that it contains. If you do not set this property, then the left block will overlap the right block.

7

The content of the left side is generated by processing the element in mode="label.markup", which generates the section number alone. Note that in this case it actually processes the parent section element, because section.heading is called by the template that matches the section title element, not by the section itself.

8

The fo:list-item-body contains the right text. Its start-indent property uses a special XSL-FO body-start() function to compute the indent the left side of the block that it contains.

9

The content of the right side is generated by processing the element in mode="title.markup", which generates the section title alone.

10

Replace the use of $title with $title.block in each of the xsl:when clauses that follow.


Any number of variations can be used. For example, if you use text-align="end" on the fo:list-item-label, then the section number will be right-aligned in its space, separated from the left-aligned title by the provisional-label-separation distance. Other elements can be formatted using similar techniques.