link

PrintCSS

Running Headers and Footers

If you want to use HTML inside the page margin boxes, you will need to use running elements. These elements are normal HTML nodes with the CSS position property set to running(NAME).

The name given to the running element is used within the page margin boxes to set their content to the running element's inner HTML.

To do so, you need to set the specific page margin box’s CSS content property to element(NAME), where NAME is the given running element name.

Elements with the position running do not appear in the document until you assign them to some CSS content property.

Your running elements must come first in your HTML structure. For example, if you put the footer element before the closing body tag, the running footer will only appear on the last page.

#Sample Header

So after reading the theory, let’s jump right in and create a small example. We will define a running header with simple text and a footer with HTML content.

In the body of our document, let’s define our two header div elements.

<div class="headerLeft">
    Running Headers and Footers
</div>
<div class="headerRight">
    A sample document
</div>

As mentioned above, we now need to define the position as running, and we will also give our header elements some basic style.

.headerLeft {
    position: running(headerLeft);
    font-size: 12pt;
}

.headerRight {
    position: running(headerRight);
    font-size: 8pt;
    font-style: italic;
    text-align: right;
    color: #667eea;
}

Before we render the PDF, we need to define the page margin boxes and the page in CSS.

@page  {
    size: A6;
    margin: 20mm;

    @top-left {
        content: element(headerLeft);
        border-bottom: 2px solid #434190;
    }

    @top-center {
        border-bottom: 2px solid #434190;
    }

    @top-right {
        content: element(headerRight);
        border-bottom: 2px solid #434190;
    }
}

As you can see, the page size is A6, and we have a margin of 2cm for all sides of the page. Our running header elements are used in the @top-left and @top-right definition. Additionally, I added a bottom border to all top margin boxes.

The rendering result always depends on the tool you are using. Here are two samples with PDFreactor and Prince.

Result with Prince
Result with Prince
PDFreactor Result
PDFreactor Result

More tools you can check on printcss.live.

Now, as we have the header ready, let’s have a look at the footer. I want to put a logo on the left side and contact information on the right in the footer. Between both, I want to add the current and total page numbers.

<div class="footerLeft">
    <img src="https://printcss.live/img/logo.png" />
</div>
<div class="footerRight">
    <a href="mailto:info@azettl.net">info@azettl.net</a>
    <br />
    <a href="https://printcss.live/">printcss.live</a>
</div>

In the CSS, we will give the footer classes a position running again and some basic style like the logo’s width.

.footerLeft {
    position: running(footerLeft);
}

.footerLeft img {
    width: 20mm;
}

.footerRight {
    position: running(footerRight);
    text-align: right;
    font-size: 8pt;
}

If we render now, we will not see the elements as we still need to assign them to one of the page margin boxes.

Result with Prince
Result with Prince

We need to define our bottom margin boxes inside the @page rule to make this work.

@bottom-right {
    content: element(footerRight);
    border-top: 2px solid #434190;
}

@bottom-center {
    content: counter(page) " / " counter(pages);
    border-top: 2px solid #434190;
    font-size: 8pt;
}

@bottom-left {
    content: element(footerLeft);
    border-top: 2px solid #434190;
}

Again I added some border, this time on the top. Also, you can see in the bottom center margin box I define the content as counter(page) ‘ / ‘ counter(pages). The counter page returns us the current page number, while the pages counter gives us the total number of pages.

Now our document has a nice header and footer.

Running header and footer rendered with PDFreactor
Running header and footer rendered with PDFreactor

#Complete Sample

To see whether our running header and footer elements actually work, we need to add some content. If our code works fine we will see the header and footer on all pages.

The content should be placed inside the body element but after all running header and footer elements.

<div class="content">
    <h1>PrintCSS: Running Headers and Footers</h1>
    <p>If you want to use HTML inside the page margin boxes, you will need to use running elements. These elements are normal HTML nodes with the CSS position property set to 'running(NAME)'.</p>
    <p>The name given to the running element is used within the page margin boxes to set their content to the running elements inner HTML.</p>
    <p>To do so, you need to set the specific page margin box's CSS content property to 'element(NAME)', where NAME is the given running element name.</p>
    <p>Elements with the position running do not appear in the document until you assign them to some CSS content property.</p>
    <p>Your running elements must come first in your HTML structure. For example, if you put the footer element before the closing body tag, the running footer will only appear on the last page.</p>
</div>

If you render on printcss.live now, you will see the running elements on all pages.

Rendering result with PDFreactor.
Rendering result with PDFreactor.

#Complete Code to copy

View on GitHub

Get Result PDF

View on the PrintCSS Playground

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>test</title>
        <style>
            @page  {
                size: A6;
                margin: 20mm;

                @top-left {
                    content: element(headerLeft);
                    border-bottom: 2px solid #434190;
                }

                @top-center {
                    border-bottom: 2px solid #434190;
                }

                @top-right {
                    content: element(headerRight);
                    border-bottom: 2px solid #434190;
                }

                @bottom-right {
                    content: element(footerRight);
                    border-top: 2px solid #434190;
                }

                @bottom-center {
                    content: counter(page) " / " counter(pages);
                    border-top: 2px solid #434190;
                    font-size: 8pt;
                }

                @bottom-left {
                    content: element(footerLeft);
                    border-top: 2px solid #434190;
                }
            }

            .headerLeft {
                position: running(headerLeft);
                font-size: 12pt;
            }

            .headerRight {
                position: running(headerRight);
                font-size: 8pt;
                font-style: italic;
                text-align: right;
                color: #667eea;
            }

            .footerLeft {
                position: running(footerLeft);
            }

            .footerLeft img {
                width: 20mm;
            }

            .footerRight {
                position: running(footerRight);
                text-align: right;
                font-size: 8pt;
            }
        </style>
    </head>
    <body>
        <div class="headerLeft">
            Running Headers and Footers
        </div>
        <div class="headerRight">
            A sample document
        </div>
        <div class="footerLeft">
            <img src="https://printcss.live/img/logo.png" />
        </div>
        <div class="footerRight">
            <a href="mailto:info@azettl.net">info@azettl.net</a>
            <br />
            <a href="https://printcss.live/">printcss.live</a>
        </div>
        <div class="content">
            <h1>PrintCSS: Running Headers and Footers</h1>
            <p>If you want to use HTML inside the page margin boxes, you will need to use running elements. These elements are normal HTML nodes with the CSS position property set to 'running(NAME)'.</p>
            <p>The name given to the running element is used within the page margin boxes to set their content to the running elements inner HTML.</p>
            <p>To do so, you need to set the specific page margin box's CSS content property to 'element(NAME)', where NAME is the given running element name.</p>
            <p>Elements with the position running do not appear in the document until you assign them to some CSS content property.</p>
            <p>Your running elements must come first in your HTML structure. For example, if you put the footer element before the closing body tag, the running footer will only appear on the last page.</p>
        </div>
    </body>
</html>