Edit online

The page headers and footers use the string sets defined for publication, chapter, and section titles. These string-sets are defined in the numbering CSS. This section contains information about how they are used in the page definitions.

Edit online

The headers and footers are part of the page definitions. To see how the default page layouts are defined, see: Default Page Definitions.

Edit online

To change the font for all the headers and footers, in your customization CSS add a CSS rule similar to this:

@page {
    font-size: 12pt;
    font-family: "Arial";
}
Important: These settings apply to all page margin boxes, but not to the text inside the page.

If you want to change the settings only for a specific page type (for example, the table of contents), use the name of the page:

@page table-of-contents {
    font-size: 12pt;
    font-family: "Arial";
}

Edit online

A common use-case is to add a background image to one of the page corners.

@page :left {
    @bottom-left-corner{
        content: " ";
        background-image: url('https://www.oxygenxml.com/resellers/resources/OxygenXMLEditor_icon.svg');
        background-repeat:no-repeat;
        background-position:50% 50%;        
    }
}
Important: Always specify a content property. If not, the page margin box will not be generated.

Another use-case is to use one of the @top-left or @top-right page margin boxes. These boxes have an automatic layout and they can be very small if they have no content. If there is no text to be placed over the image, use a series of non-breaking spaces (\A0) to increase the box width as in the following example (alternatively, you can use the technique described in How to Decorate the Header by Using a Background Image on the Entire Page):

@page :left {
    @top-left{
        content: '\A0\A0\A0\A0\A0\A0\A0\A0\A0\A0';
        background-image: url('https://www.oxygenxml.com/resellers/resources/OxygenXMLEditor_icon.svg');
        background-repeat:no-repeat;
        background-position:50% 50%;
    }
}
Note: You can use raster image formats (such as PNG or JPEG), but it is best to use vector images (such as SVG or PDF). They scale very well and produce better results when printed. In addition the text from these images is searchable and can be selected (if the glyphs have not been converted to shapes) in the PDF viewer.

Edit online

If you need to style a fragment of text (for example, a company slogan) with certain colors or font styles, you have several options:
  • Use an SVG image as background for a page margin box or for the entire page. See: How to Add a Background Image to the Header.
  • Use the oxy_label constructor. This is a function that creates a text label with a set of styles.
    @page {
        @top-right {
            content: oxy_label(text, "My Company", styles, "color:red; font-size: larger;") 
                     ' ' 
                     oxy_label(text, "Product", styles, "color:blue; text-decoration:underline;"));
        }
    }
    You can combine the oxy_label with oxy_xpath, to extract and style a piece of text from the document:
    content: oxy_label(text, oxy_xpath("/some/xpath"), styles, "color:blue; "));
    Note: These functions work only with the Chemistry CSS processor.
  • Use two adjacent page margin boxes, and style them differently:
    @page {
      @top-center {
        content: "First part";
        color: red;
        text-align:right;
      }
      @top-left {
        content: "- Second part";
        color: blue;
        text-align:left;
      }
    }

Edit online

The headers display information such as map title, part title, chapter title, and section title, ending in the page number.

content: string(maptitle) string(parttitle) string(chaptertitle) string(sectiontitle) " | " counter(page);

This might be too much if you have long titles. The solution is to override the default header content.

In your customization CSS, add the following CSS rule:

@page :left {
    @top-left {
        content: string(chaptertitle) " | " counter(page);
    }
}
@page :right{
    @top-right {
        content: string(chaptertitle) " | " counter(page);
    }
}
Important: Some of the CSS default page rules are more important. If you see that the content does not change, you should try to specify also the name of the page:
@page :left, table-of-contents:left, chapter:left{
  ...
}
@page :right, table-of-contents:right, chapter:right{
  ...
}

Edit online

There are a number of strings defined for part, chapter, and sections. Each of these strings start with the " | " character as a separator. For example, in the header of a page, you may find a sequence of strings:
My Publication | Introduction | Getting Started 
  1. "My Publication" is the value of the maptitle string.
  2. "Introduction" is the value of the chaptertitle string.
  3. "Getting Started" is the value of the sectiontitle string.

There might be cases where you want to change this separator. You will need to recompose the header content using the above string sets. Suppose you want to use " - " as a separator. In your customization CSS, add the following CSS rule:

*[class ~= "topic/topic"][is-part] > *[class ~= "topic/title"] {
    string-set: parttitle " - " counter(part, upper-roman) " - " content(), chaptertitle  ""; /* Avoid propagating a past chapter title on a new part */
}
*[class ~= "topic/topic"][is-chapter]:not([is-part]) > *[class ~= "topic/title"] {
    string-set: chaptertitle " - " counter(chapter) " - " content();
}

If you enabled the Deep Numbering - Built-in CSS, then use:

/* 
 * Alter the string sets that are shown in the header of the page.
 */
*[class ~= "topic/topic"][is-part] > *[class ~= "topic/title"] {
    string-set: parttitle " - " counter(part, upper-roman) " - " content(), chaptertitle  ""; /* Avoid propagating a past chapter title on a new part */
}
*[class ~= "topic/topic"][is-chapter]:not([is-part]) > *[class ~= "topic/title"] {
    string-set: chaptertitle " - " counter(chapter) " - " content(), sectiontitle "";
}
*[class ~= "topic/topic"][is-chapter]:not([is-part]) > *[class ~= "topic/topic"] > *[class ~= "topic/title"] {
    string-set: sectiontitle " - " counter(chapter) "." counter(section1) " - " content();
}

Edit online

To modify the styling of the default page headers, add the following CSS rule in your customization CSS:

@page :left {
    @top-left {
        color:navy;
        font-style:italic;
    }
    @top-right {
        color:red;
    }
}

If you intend to modify just the headers of the table of contents, use the table-of-contents page rule selector:

@page table-of-contents:left {
    @top-left {
        color:navy;
        font-style:italic;
    }
    @top-right {
        color:red;
    }
}

Edit online

A very simple approach is to use the oxy_xpath directly in the content property:

@page front-page {    	
     @top-center {
          content: "Created: " oxy_xpath('//*[contains(@class, " topic/created "][1]');
     }
}

Example 1: Compute the Number of Words

The following example computes the number of words from the publication. It counts all the words, including the ones from the TOC, but does not take the static labels into account:

@page front-page {
     @bottom-center {
          content: "Number of words: " 
                    oxy_xpath("string-length(normalize-space(/)) - \
                               string-length(translate(normalize-space(/),' ','')) +1");
     }
}
Note: The XPath expression from the page rules is evaluated in the context of the document root element, so you will need to use absolute expressions starting with / or //. This is different from the case when the oxy_xpath is used in CSS rules that match an element. In this case, the XPath expressions are evaluated in the context of the matched element and you can use relative paths.
Tip: XPath 2.0 is supported (not schema aware).

Example 2: Retrieve Image from a Document and Insert it in the Header

Another example is to use an image from the document in the publication header:
<bookmeta>
  <metadata>
   ...
    <data name="cover">
        <image href="product-cover.png" outputclass="cover-image"/>
    </data>
   ...
  </metadata>
</bookmeta>
@page {
   @top-center {
        content: url("oxy_xpath('//*[contains(@outputclass, "cover-image")]/@href')");
   }
}

If the URL returned by oxy_xpath is not absolute, it is considered to be relative to the CSS file. To obtain an absolute URL from one relative to the XML document, you can use in the XPath expression functions like resolve-uri and document-uri:

@page {
   @top-center {
        content: url(oxy_xpath("resolve-uri(//*[contains(@outputclass, 'cover-image')]/@href), document-uri(/))"));
   }
}

Example 3: Insert the Current Date in the Footer

Another example is to use the oxy_xpath function to compute the current date and insert it in the publication footer:

@page {
    @bottom-left {
        content: oxy_xpath('current-date()');
    }
}

Edit online

It is possible to dynamically change an image in the header depending on the chapter. For this, you need to define an image reference in the metadata section of each chapter. One way is to specify it in the DITA map by using the <topicmeta> element for the <chapter> topic reference:

...
 <chapter href="topics/installing.dita">
    <topicmeta>
      <data name="header-image" value="img/installing.png"/>
    </topicmeta>
    ...

In the above example, there is set of key value pairs with the name header-image. The img/installing.png is an image reference relative to the DITA map URI. This information is automatically copied into the content in the merged map file, like this:

<topic is-chapter="true" ... >
    <title class="- topic/title ">Installing</title>
    <shortdesc class="- topic/shortdesc ">You install components to make them available for your
      solution.</shortdesc>
    <prolog class="- topic/prolog ">
      ...
      <data class="- topic/data " name="header-image" value="img/installing.png"/>
      ...

This information can be picked up from CSS:

/* Define the string set variable that contains an URL */
*[class ~= "topic/topic"] *[class ~= "topic/data"][name="header-image"] {
  string-set: imgst oxy_url(oxy_xpath('/*/@xtrf'), attr(value));
}

/* Using the value='none' stops applying the image. */
*[class ~= "topic/topic"] *[class ~= "topic/data"][name="header-image"][value="none"] {
  string-set: imgst "";
}

/* Use the string set variable in one of the page margin boxes. */
@page chapter {  
  @top-left-corner {
    content: string(imgst);
    font-size:0; /* remove the font ascent and descent */
  }
}

Details: The @value attribute is used to build a URL relative to the URI of the DITA map. To determine the base URI of the DITA map, the @xtrf attribute was used from the root element of the merged map document, extracted using the oxy_xpath function.

Notes:
  • The image is always aligned vertically to the middle of available space from the page margin box.
  • Make sure you use an image of the correct size. For example, if you want to place the image in the top-left corner of the page, assuming the top and left page margins are 1 in, then make sure the image is a square having a size of 1 in.
  • The image is applied to all pages that follow the data element, until another data element changes it:
    ...
     <chapter href="topics/installing.dita">
        <topicmeta>
          <data name="header-image" value="img/installing.png"/>
        </topicmeta>
     </chapter>
     <chapter href="..."> <!-- Uses the same installing.png image -->
     <chapter href="..."> <!-- Uses the same installing.png image -->
     <chapter href="..."> <!-- Uses the same installing.png image -->
     <chapter href="topics/change.dita">
        <topicmeta>
          <data name="header-image" value="img/change.png"/>
        </topicmeta>
     </chapter>
     <chapter href="..."> <!-- Uses the same change.png image -->
     <chapter href="..."> <!-- Uses the same change.png image -->
     <chapter href="..."> <!-- Uses the same change.png image -->
    
    To clear the image, use the none value:
    ...
          <data name="header-image" value="none"/>
     ...

Edit online

There are two ways to add a horizontal line under the header.

Method 1: Add a Border in the Page Margin Boxes

To add a horizontal line that would stretch across the width of the page, add a bottom border to each of the 5 margin boxes in the top side of the page (top-left-corner, top-left, top-center, top-right, top-right-corner).

If you consider that the space between the header and the bottom border is too large, you could also change the alignment by adding a vertical-align: bottom; declaration in the page margin boxes.

For example, if you need to set some text as a header in the top-left margin box and insert a horizontal line under it, the customization CSS would look something like this:
@page chapter, chapter:first:left:right, front-page{

   padding-top: 1em;
 
  @top-left {
    content: "Custom header";
    color: gray;
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }

  @top-center{
    content:" ";
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }

  @top-right{
    content:" ";
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }

  @top-right-corner{
    content:" ";
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }

  @top-left-corner{
    content:" ";
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }
Note: The padding-top: 1em; is used to avoid the border at the bottom of the header that joins with the page content.

Method 2: Use a Background Image

An alternative method is to add a horizontal line/border under an existing header (or in any other part of the page) using an SVG image, as described in How to Add a Background Image to the Header.