Styling Visualforce PDFs

February 1, 2016

The below guide is useful in cases when you want to

  • Add Header and Footer to PDF Documents
  • Repeat Table Header on every page
  • Adding border to tables

First, to add styles to a Visualforce PDF, you need to have these 2 attributes in the apex:page tag

renderAs="pdf" applyBodyTag="false"

Next, you need to define your styles in the tag

<head>
<style>
//All styles go here
</style>
</head>

To add Header and Footer
We use the @page rule of CSS for this. It lets you specify the format of the page like size, margin, header and footers.
To define header and footer, we make use of the @top-center, @top-left, @top-right, @bottom-center etc attributes which define the position of the text in the header and footer sections of the page.

Below is a sample

<style>
@page {
size: A4;
@top-left {
content: "Company Name - {!merge_field}";
}
@top-right {
content: "Document Name - {!merge_field}";
}
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
}
}
</style>

Repeat Table Header
To repeat the table header on every page incase the table spans across multiple pages, the table structure needs to be HTML5 compliant along with a few styles that we apply.
The table structure should contain and tags

<table>
<thead>
<tr>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Text</td>
</tr>
</tbody>
</table>

Fortunately, if you use the apex:dataTable tag, Salesforce automatically generates this for you.
After which below is the style you have to apply to repeat table headers.

table{
-fs-table-paginate: paginate;
border-collapse: collapse;
border-spacing: 0;
}

Adding Border to Tables
Below is the basic CSS you have to apply to get a border on a table.

td,th{
border: 1px solid black;
word-wrap: break-word;
}

After this, you might observe that there is a space between each column in the table, to avoid which you have to apply the below style

table{
border-collapse: collapse;
border-spacing: 0;
}

The below style makes sure that a row isnt split across 2 pages if it has long text.

table tr, table td{
page-break-inside: avoid;
word-wrap: break-word;
}

Additional Tip: If you want to split content across multiple pages, use the below style on a placeholder tag like <div>, <span>, <p>:

page-break-after:always;

This is the final stylesheet

<head>
<style>

td,th{
border:1px solid black;
padding: 7px;
word-wrap: break-word;
}

table tr, table td{
page-break-inside: avoid;
}

table{
-fs-table-paginate: paginate;
border-collapse: collapse;
border-spacing: 0;
}

</style>
</head>