Side floats

A side float is used to position a block of content to the side of a page. The body text will wrap around the side float if it does not take up the whole width of the page, or the side float can be positioned in a side indent so it does not intrude on the text area.

The DocBook XSL print stylesheet added support for side floats starting in version 1.68 of the stylesheet. For print output, side floats only work with those XSL-FO processors that support them. Two that are known to work are RenderX's XEP and Antenna House's XSL Formatter.

The DocBook FO stylesheet provides support for several kinds of side floats:

A sidebar as side float

One common use of side floats is for the sidebar element. By default, a sidebar prints as a full-width block on the page instead of a side float. The following example shows some text in a sidebar to demonstrate how it can appear in a left side float.

<sidebar> 
<title>Sidebar example</title>
<?dbfo sidebar-width="1.5in"?><?dbfo float-type="left"?>
<para>A <sgmltag class="element">sidebar</sgmltag>
can be used to emphasize certain
content. It can intrude into
the body area, or it can
 appear in side indents as 
a margin note.</para>
</sidebar>


The formatting of a sidebar is controlled by these features:

  • sidebar.float.type parameter

  • sidebar.float.width parameter

  • sidebar.properties attribute-set

  • sidebar.title.properties attribute-set

  • Processing instructions for individual instances.

The overall behavior is controlled by the sidebar.float.type stylesheet parameter. That parameter contains one of the values of the float property as defined in the XSL-FO specification:

none

No float is used. The sidebar appears in sequence with other text blocks. This is the default value.

left

The float appears on the left side of the page.

start

The float appears on the start side of the page. For languages that read left-to-right, that is the left side of the page.

right

The float appears on the right side of the page.

end

The float appears on the end side of the page. For languages that read left-to-right, that is the right side of the page.

inside, outside

Some XSL-FO processors such as Antenna House's XSL Formatter and XEP support an extension to the spec that can position the float to the inside or outside of pages using double-sided output. Here outside means to the left on left-hand pages, and to the right on right-hand pages.

before

The float appears at the top of the page, using the full width of the page. This is not a side float, but is included here for completeness.

The sidebar.float.type sets the default location for all sidebars, but you can change the location for an individual sidebar element using a float-type processing instruction. The following is an example that will create a float on the right side of the page:

<sidebar>
<?dbfo float-type="right"?>
<title>My floating sidebar</title>
...

The width of the sidebar float is controlled by sidebar.float.width parameter, which is set to 1 inch by default. You may need to set a different width for individual sidebar elements. You can change the width for one sidebar using a sidebar-width processing instruction, such as this example:

<sidebar>
<?dbfo sidebar-width="3.5in"?>
<title>My floating sidebar</title>
...

In addition to the above properties being applied to the float container, the sidebar.properties attribute set is applied to the block of content within the container. Use that property set to change the font size, text alignment, background, or border for the content. The following example shows the default values:

<xsl:attribute-set name="sidebar.properties" 
        use-attribute-sets="formal.object.properties">
  <xsl:attribute name="border-style">solid</xsl:attribute>
  <xsl:attribute name="border-width">1pt</xsl:attribute>
  <xsl:attribute name="border-color">black</xsl:attribute>
  <xsl:attribute name="background-color">#DDDDDD</xsl:attribute>
  <xsl:attribute name="padding-left">12pt</xsl:attribute>
  <xsl:attribute name="padding-right">12pt</xsl:attribute>
  <xsl:attribute name="padding-top">6pt</xsl:attribute>
  <xsl:attribute name="padding-bottom">6pt</xsl:attribute>
  <xsl:attribute name="margin-left">0pt</xsl:attribute>
  <xsl:attribute name="margin-right">0pt</xsl:attribute> 
  <!--
  <xsl:attribute name="margin-top">6pt</xsl:attribute>
  <xsl:attribute name="margin-bottom">6pt</xsl:attribute> 
  -->
</xsl:attribute-set>

These properties draw a border around the sidebar content and add a background color. The padding properties add some space between the sidebar text and the border. The margin properties can be used to provide some space between the border and the body text that wraps around the sidebar. To learn how to customize an attribute-set, see the section “Attribute sets”.

In addition, the separate sidebar.title.properties attribute-set is applied to the sidebar's title element. Here are its default values:

<xsl:attribute-set name="sidebar.title.properties">
  <xsl:attribute name="font-weight">bold</xsl:attribute>
  <xsl:attribute name="hyphenate">false</xsl:attribute>
  <xsl:attribute name="text-align">start</xsl:attribute>
  <xsl:attribute name="keep-with-next.within-column">always</xsl:attribute>
</xsl:attribute-set>

Margin notes

Margin notes are blocks of content that are meant to appear in the empty margin area, rather than having text wrap around them like with a sidebar. By putting them in the margin area, they do not interrupt the flow of paragraphs.

The DocBook DTD does not provide a standard way of specifying margin notes. However, the FO stylesheet supports a special sidebar as a margin note. You can also implement margin notes as a customization, as described in the section “Custom margin notes”.

You can turn a sidebar element into a margin note by adding the following processing instruction:

<sidebar>
<?dbfo float-type="margin.note"?>
...
</sidebar>

When a sidebar is designated was a margin note in this way, the stylesheet applies a different set of properties to create the side float. This lets you create one style for regular sidebars, and another for margin notes.

To enable margin notes, you have to give them some open space so they do not intrude on your paragraphs. Increasing the side page margins will not work because the XSL float mechanism puts text within the body region, not outside of it in the margins. So you need to create an additional indent for all body text on the page, and the margin note floats can appear within the indent.

You can create such an indent on the left (or start side) of the page by using the body.start.indent parameter. If you want the indent on the right (or end side) of the page, then use the body.end.indent parameter. If you do not set the extra body indent, then your margin notes will intrude into the body text area. See the section “Indenting body text” for more information on these parameters. The following example indents the body text an extra 25mm on the left

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

After you have set up the indent area, you need to specify the formatting properties for margin notes. The margin.note.float.type determines the position of the margin note, using the same selection of values as for sidebar.float.type. See the section “A sidebar as side float”. Note that you cannot use the dbfo float-type processing instruction to change the position of an individual margin note. That's because that PI is already being used to indicate that a sidebar is to be handled like a margin note.

You can set the standard width for all your margin notes by using the margin.note.width parameter. To change the width for a single instance, you can use the dbfo sidebar-width processing instruction within its sidebar element. If you make a margin note wider than the enlarged margin, then the margin note will intrude into the body text, which will wrap around it.

And to give your margin notes a distinctive look, add attributes to the margin.note.properties attribute-set. That attribute-set is applied to the block that contains the content of the sidebar element. For the title element in a margin note sidebar, use the margin.note.title.properties attribute-set.

Here is a complete example of setting the parameters and attribute-sets for margin notes:

<xsl:param name="body.start.indent">30mm</xsl:param>
<xsl:param name="margin.note.float.type">start</xsl:param>
<xsl:param name="margin.note.width">27mm</xsl:param>
<xsl:attribute-set name="margin.note.properties">
  <xsl:attribute name="font-size">8pt</xsl:attribute>
  <xsl:attribute name="font-family"><xsl:value-of 
                    select="$title.fontset"/></xsl:attribute>
  <xsl:attribute name="border">0.5pt solid green</xsl:attribute>
  <xsl:attribute name="padding">3pt</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="margin.note.title.properties">
  <xsl:attribute name="font-size">9pt</xsl:attribute>
</xsl:attribute-set>

To learn how to customize an attribute-set, see the section “Attribute sets”.

Custom margin notes

You may want to turn other elements in your DocBook content into margin notes. For example, you might want to put a short phrase with a cross reference in the margin, or put a caution element in the margin. The FO stylesheet uses two templates to create margin notes, the margin.note template and the floater template.

The template named margin.note in fo/block.xsl is called by the sidebar template when the dbfo float-type="margin.note" processing instruction is used. The margin.note template applies all the margin note properties described in the section “Margin notes” to the context element that calls the template. So you would use the margin.note template when you want your customization to look like other margin notes.

Here are customizations that put a phrase or a caution element with a role="margin.note" attribute into a margin note:

<xsl:template match="phrase[@role='margin.note']">
  <xsl:call-template name="margin.note"/>
</xsl:template>

<xsl:template match="caution[@role='margin.note']">
  <xsl:call-template name="margin.note">
    <xsl:with-param name="content">
      <xsl:apply-imports/>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

Both of these customizations call the margin.note template. They differ in the use of the content parameter when the template is called. The margin.note template just does an xsl:apply-templates to the context element that calls it. That means it processes the element's children, which is appropriate for a phrase element. But if you did that with caution, then it would process the para within the caution, but not the caution element itself. So that template fills in the content parameter by doing apply-imports on the caution element, which formats the caution using the admonition templates.

Custom side float

If you need more control than is provided by the margin.note template, then you can call the template named floater, which is also in fo/block.xsl. This is the template that actually creates a side float in the FO output, and it is called by the sidebar and margin.note templates. The floater template takes several parameters to define the float, and does not apply any formatting properties to the content. Thus you can use it to create custom side floats from any element.

The following is an example of using floater to put an admonition icon into the side margin:

Example 13.16. Custom side float

<xsl:param name="body.start.indent">1.5in</xsl:param> 1
<xsl:param name="title.margin.left">0pc</xsl:param>  2
<xsl:param name="admon.textlabel" select="0"/>  3

<xsl:template match="note|caution|warning|tip|important">  4
  <xsl:call-template name="floater">  5
    <xsl:with-param name="position">left</xsl:with-param>  6
    <xsl:with-param name="width">0.5in</xsl:with-param>  7
    <xsl:with-param name="start.indent">0.5in</xsl:with-param>  8
    <xsl:with-param name="content">  9
      <fo:block margin-top="1em"
                padding="3pt"
                text-align="center"
                border="1pt solid grey">
        <fo:external-graphic width="auto" height="auto">
          <xsl:attribute name="src">
            <xsl:call-template name="admon.graphic"/>
          </xsl:attribute>
        </fo:external-graphic>
      </fo:block>
    </xsl:with-param>
  </xsl:call-template>
  <xsl:apply-imports/>  10
</xsl:template>

1

Establish a side margin area by indenting the body text 1.5 inches.

2

Set title.margin.left to zero so it does not conflict with the body.start.indent.

3

Turn off the admonition text label such as Note so only the icon is used to identify the admonition. You can leave the label if you like.

4

Customized template to match on all admonition elements.

5

Call the template named floater to create a side float.

6

Indicate the position of the float. The default value is none, so pick one of the values listed in the section “A sidebar as side float” to put it in the margin.

7

You can specify the width of the side float container.

8

You can specify an indent for the side float container.

9

Fill the content parameter with whatever you want to appear in the side float. In this case, it is an admonition graphic, selected using the admon.graphic template. It is wrapped in an fo:block, which is used to format the content.

10

Now actually process the admonition element by using xsl:apply-imports. This uses the admonition templates imported from the DocBook stylesheet.


Clearing a side float

The formatting for a side float includes wrapping the content that follows the float in the source document around the side of the float. However, there may be times when this wrapping is not appropriate. For example, if a float is followed by a short paragraph and then the start of a new section, then the section title may be wrapped next to the float.

Any elements that you want to force below any side floats should have an XSL-FO clear="both" property added to its fo:block. For sections, this can be done with the attribute-set named section.title.properties:

<xsl:attribute-set name="section.title.properties">
  <xsl:attribute name="clear">both</xsl:attribute>
</xsl:attribute-set>

You could instead create a processing instruction and matching template to output an empty block with the clear property. Any elements that follow the processing instruction will start below the side float. Here is a template to add to your customization layer:

<xsl:template match="processing-instruction('float-clear')">
   <fo:block clear="both"/>
</xsl:template>

Then insert <?float-clear?> in your content where you want the break to occur.