CSS and paged media

CSS can do more than styling websites!

Unlike websites, which are not constrained by any physical size, paged media (such as documents or books) are limited by the size of the target page (e.g. an A4 page). Fortunately, CSS (Cascading Style Sheets) supports paged media and provides a range of properties and concepts that can be used to control the flow of your document on a paged document.

@page at rule

The @page at-rule is used to specify the dimensions, margins, and other layout properties of a page.

@page  {
    /* Some samples of different page sizes */
    size: A4 landscape;
    margin: 25mm;
    background: red;
}

Page break control

break-before and break-after: These properties can be used to specify where a page break should or should never occur before or after an element.

break-inside: This property can be used to prevent a page break from occurring within an element.

orphans and widows: These properties can be used to specify the minimum number of lines that must appear at the top or bottom of a page before a page break is allowed.

Page Size

The @page rule lets you configure your page. You can set things like size, margins and backgrounds.

Auto page height

While not considered an official standard, you have the option to set the page height to 'auto' in which case the PDF will adjust its height to accommodate the content. You can also refine the result by using the min-height and max-height properties for further customization.

@page  {
    /* Auto page height */
    size: 400mm auto;
    min-height: 200mm;
    margin: 20mm;
}

Page Margins

When you define a page with margins, the space between the edge of the page and the inner margin border is called the page margins. Each side of the page is split into three margin areas: left, center, and right (for horizontal margins) or top, middle, and bottom (for vertical margins). Additionally, there are four corner areas, making a total of 16 margin areas.

Each area can be access using a @rule inside the @page rule.

@page {
    size: A4;
    margin: 2cm;

    /* TOP 3 MARGIN AREAS */
    @top-left {
        content: 'left';
        background: yellow;
    }
    @top-right {
        content: 'right';
        background: red;
    }
    @top-center {
        content: 'center';
        background: green;
    }
    
    /* BOTTOM 3 MARGIN AREAS */
    @bottom-left {
        content: 'left';
        background: yellow;
    }
    @bottom-right {
        content: 'right';
        background: red;
    }
    @bottom-center {
        content: 'center';
        background: green;
    }
    
    /* LEFT 3 MARGIN AREAS */
    @left-top {
        content: 'top';
        background: yellow;
    }
    @left-bottom {
        content: 'bottom';
        background: red;
    }
    @left-middle {
        content: 'middle';
        background: green;
    }
    
    /* RIGHT 3 MARGIN AREAS */
    @right-top {
        content: 'top';
        background: yellow;
    }
    @right-bottom {
        content: 'bottom';
        background: red;
    }
    @right-middle {
        content: 'middle';
        background: green;
    }
    
    /* 4 CORNER MARGIN AREAS */
    @bottom-left-corner {
        content: 'bl';
        background: #587b80;
    }
    @bottom-right-corner {
        content: 'br';
        background: #587b80;
    }
    @top-left-corner {
        content: 'tl';
        background: #587b80;
    }
    @top-right-corner {
        content: 'tr';
        background: #587b80;
    }
}

Page Areas

Sometimes, the page margins may not provide enough flexibility for your layout needs. In these cases, you can use page areas to create additional layout spaces on the page. Page areas are essentially absolute positioned areas on the page, but they are rendered like the margin areas in the context of the page.

@page {
    size: 200px 300px;
    margin: 50px 10px 30px 10px;

    @area foobar {
        content: 'Position me like asboulte elements';
        text-align: center;
        left: 10mm;
        right: 10mm
        bottom: 10mm;
        height: 40mm;
    }
}

Header and Footers with running elements

When playing around with Page Margins and Page Areas, you will quickly realize that placing simple content text is not enough. How about adding actual HTML content in your page margins that repeat for each page. This is done using running elements.

Running elements are basically HTML elements inside your document that are moved out of the content flow into the page context.

This involves two steps, you first need to define which element should be running, this is done by using the position property and the function running(<identifier>). The identifier can be any valid identifier and will be used as id.

<body>
    <div id="header">
        Any header content can go here
    </div>

#header {
    /* Position element as running with the id "my-header" */
    position: running(my-header);
}

The second step is to tell the margin area to use a running element as content using the content property and element(<identifier>) function with the same identifier ID.

@page {
    size: A4;
    margin: 5cm 2cm 2cm 2cm;
    
    @top-center {
        content: element(my-header);
    }
}

That's it, now you the element @header gets repeated on each page. Of cause you can also have another element for other page elements such as footer.

If you plan on adding a footer on each page, make sure the footer element is at the beginning of your document flow not at the end.

Last updated