/

HTML PDF Templates

Zoho ERP includes standard PDF templates with built-in customisation options. If you need more control over the design and structure of PDFs created for custom modules, you can build templates from scratch using HTML and CSS.

Note: This feature is available only for Custom Modules and is currently in early access. Email support@zohoerp.com to enable it for your organization.


Rendering Capabilities and Limitations

Before creating an HTML PDF template, understand which HTML elements and CSS properties the rendering engine supports. Zoho ERP uses the Flying Saucer rendering engine, which supports a subset of HTML and CSS standards.

Flying Saucer Limitations

Zoho ERP uses the Flying Saucer rendering engine to generate PDFs. Since Flying Saucer is designed for XHTML and CSS 2.1, the following limitations apply:

  • Flexbox, Grid, and CSS animations are not supported.
  • Sticky and fixed positioning are not supported.
  • Transforms, transitions, filters, 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 instead.
  • All HTML tags must be properly closed, attributes must be quoted, and tags must be nested correctly.
  • Malformed inline CSS will be ignored.
  • Pseudo-elements (::before, ::after) work, but complex pseudo-classes like :nth-child and :not may not work reliably.
  • HTML5 semantic tags such as <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 and large elements may split across pages.
  • Page numbering must be configured manually using CSS counters.
  • Custom list-style images may not render.

Supported HTML Tags

HTML PDF Templates support a limited set of HTML tags.

CategoryTags
Structuraldiv, p, span, table, thead, tbody, tfoot, pre
Text Formattingb, strong, small, label, sup, sub, font
Listsul, ol, li
Mediaimg
Linksa
Headingsh1-h6
Othershr

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 subset of CSS 2.1.

CategoryProperties
Layoutdisplay, float, position
Positioningtop, bottom, left, right
Box Modelmargin, padding, border
Text Stylingfont-*, text-align, line-height
Colourscolor and background properties
Page Breakspage-break-before, page-break-after, page-break-inside
Tablestable layout properties

Note: Modern CSS features like Flexbox, Grid, and CSS animations are not supported.


Create an HTML PDF Template

You can build an HTML PDF template from scratch for a custom module. To do this:

  • Go to Settings in the top right corner of the page.
  • Select PDF Templates under Customization.
  • Select the required custom module in the Templates pane.
  • Click + New in the top right corner.
  • Click Build From Scratch.

You can then structure the template using the following elements.

Define Page Layout and Page Rules

Use the @page CSS rule to control the page size, margins, and layout.

The @page rule can control:

  • Page size
  • Margins and padding
  • Borders and background
  • Header and footer placement
  • Page numbering
@page {
  /* Page-level CSS */
}

Global Page Styles

Apply this to all pages in the document.

@page {
  margin: 20px;
  border: 1px solid #ccc;
}

You can also use page-specific selectors such as :first, :left, and :right when different pages need different layouts.

Page-Specific Styles

First Page

@page :first {
  /* First page only */
}

Left Pages (Even Pages)

@page :left {
  /* Left-hand pages */
}

Right Pages (Odd Pages)

@page :right {
  /* Right-hand pages */
}

Add Headers and Footers

You can add content to the Header and Footer tabs in the editor.

  • Click the Header or Footer tab.
  • Enter the required content.
  • To use different content for the first page, enable the separate header or footer option for pages after the first page.
  • Enter the required content in the first page and subsequent page sections.
  • Click Run Code to preview the output.

Configure Pagination Using CSS Counters

You can add page numbers using CSS counters.

Use one of these approaches:

  • Using a custom footer class
  • Using separate page number and total page elements

Use this when page numbering needs to appear with other footer content.

<div class="my-custom-pagination-class-name"></div>
.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.

Using Separate Page Number and Total Page Elements

Use this when you want independent styling and placement.

.pagination {
  font-size: 12px;
  text-align: center;
}

.pageNumber::after {
  content: counter(page);
}

.totalPages::after {
  content: counter(pages);
}
<div class="pagination">
  Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>

Insert Dynamic Content Using Placeholders

Use placeholders in the template to render dynamic values such as record details, field values, and table data.

<p>Customer Name: ${invoice.customer_name}</p>

Click Insert Placeholders to add placeholders to the template.


Apply Conditional Rendering

Use conditions in the template when you want to show specific content only when a field has a value or when a condition is met.

Show content if a value exists:

${#invoice.field_placeholder}
  <div>Field exists</div>
${/invoice.field_placeholder}

Show content if a value does not exist:

${^invoice.field_placeholder}
  <div>Field missing</div>
${/invoice.field_placeholder}

Use equality conditions:

${#`invoice.status = Paid`}
<div>Paid Invoice</div>
${/`invoice.status = Paid`}

Use inequality conditions:

${^`invoice.status = Paid`}
<div>Unpaid Invoice</div>
${/`invoice.status = Paid`}

Render Tables and Line Items

Use HTML tables to render line items and other tabular data in the PDF.

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 using <div> or <span> inside table headers.


Use Functions

You can use functions to perform calculations, comparisons, formatting, and logical checks directly in your template.

Function syntax:

${`FUNCTION_NAME(arguments)`}

Supported function types:

Learn more about the Functions Library.

  • Click Save in the top right corner after you’ve customized the PDF template.

You can also edit a template, mark it as default, clone it, mark it as inactive, mark it as active, or delete it.