HTML PDF Template
Zoho Books provides a default set of PDF templates with basic customization options. If you need your PDFs to fully reflect your brand identity, you can use the built-in HTML and CSS editors to design templates from scratch.
Note: This feature is currently available for Custom Modules.
Rendering Capabilities and Limitations
Before creating an HTML PDF template, understand which HTML elements and CSS properties the rendering engine supports. Zoho Books uses the Flying Saucer rendering engine, which supports a subset of HTML and CSS standards.
Flying Saucer Limitations
Zoho Books uses the Flying Saucer rendering engine to generate PDFs. Since Flying Saucer is designed for XHTML and CSS 2.1, the following limitations apply:
- Features like Flexbox, Grid, and CSS animations do not work.
- Sticky and Fixed positioning are not supported.
- Transforms (e.g., rotate, scale), transitions, and filters are ignored.
- Gradients, backdrop filters, and clip-path are not supported.
- Only PNG, JPEG, and GIF image formats are supported.
- Relative image URLs do not work. Use absolute URLs or inline images (data URIs) instead.
- All HTML tags must be properly closed (e.g., <br />, <img />), attributes must be quoted, and tags must be correctly nested. Broken structure may break the PDF layout.
- Malformed inline CSS is ignored.
- Pseudo-elements (::before, ::after) work, but complex pseudo-classes like :nth-child and :not may not work reliably.
- HTML5 semantic tags like <section>, <article>, and <video> are not supported.
- SVG support is limited.
- Right-to-left (RTL) text and Unicode complex scripts may not render correctly.
- Long tables or elements that span multiple pages may split awkwardly or overlap.
- Page numbering must be implemented manually using CSS counters.
- Custom list-style images (list-style-image) may not render.
Supported HTML Tags
HTML PDF Templates support a specific set of HTML elements for structuring content. Supported tags include (but are not limited to):
| Category | Tags |
|---|---|
| Structural | div, p, span, table, thead, tbody, tfoot, pre |
| Text formatting | b, strong, small, label, sup, sub, font |
| Lists | ul, ol, li |
| Media | img |
| Links | a |
| Headings | h1–h6 |
| Others | hr |
Common attributes such as id, class, style, align, width, and height are supported where applicable.
Note: Only supported tags will render correctly in the generated PDF.
Supported CSS Properties
HTML PDF Templates support a wide subset of CSS 2.1 for styling and layout. Supported categories include:
| Category | Properties |
|---|---|
| Layout | display, float, position |
| Positioning properties | top, bottom, left, right |
| Box model | margin, padding, border |
| Text styling | font-*, text-align, line-height |
| Colors | Color and background properties |
| Page breaks | page-break-before, page-break-after, page-break-inside |
| Tables | Table layout properties |
Note: Modern CSS features like Flexbox, Grid, and CSS animations are not supported.
Create an HTML PDF Template
You can build a PDF template from scratch using HTML PDF Templates, which allow you to design PDFs using HTML and CSS, either independently or together.
To build an HTML PDF template:
- Go to Settings in the top right corner.
- Click PDF Templates under Customization.
- Click the required custom module from the Templates pane.
- Click + New in the top right corner.
- Click Build From Scratch in the top right corner.
The process of creating an HTML PDF template is divided into the following stages:
- Define page layout and page rules
- Add headers and footers
- Configure pagination
- Insert dynamic content using placeholders
- Apply conditional rendering
- Render line items and tables
- Use Functions
Define Page Layout and Page Rules
Before adding content, define the overall page layout using the @page CSS rule. Page rules control how each page of the PDF is rendered.
What @page controls:
- Page size
- Margins and padding
- Borders and background
- Header and footer placement
- Page numbering
@page {
/* Page-level CSS */
}Global Page Styles
Applied to all pages in the document.
@page {
margin: 20px;
border: 1px solid #ccc;
}Page-Specific Styles
Used when different pages require different layouts.
First Page
Used to apply styles only to the first page of the document.
@page :first {
/* First page only */
}Left Pages (Even pages)
Used to apply styles to all left-hand (even-numbered) pages.
@page :left {
/* Left-hand pages */
}Right Pages (Odd pages)
Used to apply styles to all right-hand (odd-numbered) pages.
@page :right {
/* Right-hand pages */
}Add Headers and Footers
You can add headers and footers from the Header and Footer tabs in the HTML editor. To add them:
- Click the required tab, Header or Footer, in the HTML editor.
- Enter the header or footer content in the text box.
- To use a different header for the first page and a common header for the remaining pages, click Add a separate header for pages after the first page. Then, enter the common header content in the Header for Subsequent Page section.
- To use a different footer for the first page and a common footer for the remaining pages, click Add a separate footer for pages after the first page. Then enter the common footer content in the Footer for Subsequent Page section.
- Click Run Code to preview your changes. Press Command and + on Apple devices, and Control and / on Windows devices.
Configure Pagination Using CSS Counters
You can add page numbers using CSS counters. Define the page numbers inside the footer and render them using the counter() function.
There are two ways to set up pagination:
Using a Custom Footer Class
This method appends page numbers to an existing footer container using a custom CSS class. Use this when you want page numbers to appear alongside other footer content like disclaimers or document labels.
To add page numbers using a custom footer class:
Add the footer HTML (in the HTML tab):
<div class="my-custom-pagination-class-name"></div>Add the CSS (in the CSS tab):
.my-custom-pagination-class-name::after {
content: " | Page " counter(page) " of " counter(pages);
}Here:
- counter(page) returns the current page number.
- counter(pages) returns the total number of pages.
- The counter() function works only inside pseudo-elements such as ::after.
This will render output in the format: Invoice - PDF Template | Page 1 of 5
Using Separate Page Number and Total Page Elements
This method places the current page number and total page count in separate elements, giving you more control over styling and positioning each value in the footer.
CSS:
.pagination {
font-size: 12px;
text-align: center;
}
.pageNumber::after {
content: counter(page);
}
.totalPages::after {
content: counter(pages);
}HTML:
<div class="pagination">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>This will display the page number at the center of the footer with a font size of 12px.
Insert Dynamic Content Using Placeholders
You can insert dynamic data into your template using placeholders.
<p>Customer Name: ${invoice.customer_name}</p>Placeholders can be placed anywhere inside valid HTML. Click Insert Placeholders to add them to the template.
Apply Conditional Rendering
You can show or hide sections of HTML based on specific conditions.
Show content if value exists:
${#invoice.field_placeholder}
<div>Field exists</div>
${/invoice.field_placeholder}Show content if value does not exist:
${^invoice.field_placeholder}
<div>Field missing</div>
${/invoice.field_placeholder}Equality condition:
${#`invoice.status = Paid`}
<div>Paid Invoice</div>
${/`invoice.status = Paid`}Inequality condition:
${^`invoice.status = Paid`}
<div>Unpaid Invoice</div>
${/`invoice.status = Paid`}Render Line Items and Tables
Line items are rendered by looping through rows using Mustache-style sections.
${#sales_receipt.line_items}
<tr>
<td>${name}</td>
<td>${quantity}</td>
<td>${rate_formatted}</td>
</tr>
${/sales_receipt.line_items}Example:
<table>
<thead>
<tr>
<th>Description</th>
<th>Qty</th>
<th>Unit Price</th>
</tr>
</thead>
<tbody>
${#TableCF.cm_products}
<tr>
<td>${TableCF.cm_products.cf_description.Value}</td>
<td>${TableCF.cm_products.cf_quantity.Value}</td>
<td>${TableCF.cm_products.cf_unit_price.Value}</td>
</tr>
${/TableCF.cm_products}
</tbody>
</table>Note: Use only <tr> and <th> inside <thead>, and <tr> and <td> inside <tbody>. Avoid <div> or <span> inside table headers.
Use Functions
You can use functions to perform calculations, comparisons, formatting, and logical checks directly inside your PDF template.
The syntax for functions is:
${`FUNCTION_NAME(arguments)`}The supported function types are:
Learn more about the functions library.
Click Save in the top right corner after you’ve customized the PDF template.
You can also edit, mark as default, clone, and delete the template you created.