Design
HTML templates
The basic to advanced usage of HTML templates with Carbone
COMMUNITY FEATURE
Available for:
Carbone Cloud
Carbone On-premise
Embedded Carbone JS
v5.0+
Carbone supports HTML as both an input template and an output format, enabling you to generate PDFs, emails, and other documents directly from HTML templates. HTML templates in Carbone support a wide range of features, including substitutions, repetitions, formatters, translations, conditions, and all enterprise features, making them a versatile choice for document generation.
Basic
Carbone needs 2 elements to generate a document:
- A JSON data: coming from your application / database / API (e.g. the following JSON)
- A HTML Template: made from an existing website, email, or from you code editor. The following template includes Carbone tags: the
{d.user.firstName}
,{d.user.lastName}
,{d.user.email}
, and{d.user.membershipLevel}
. These tags will be replaced with the corresponding values from the JSON data.
The d in {d.user.firstName} refers to the root of your JSON data. The path after d (e.g., user.firstName) must match the structure of your JSON. You can use any valid HTML structure; Carbone will only replace the tags with the corresponding data.
{
"user": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@carbone.io"
},
"membershipLevel": "Premium"
}
<!DOCTYPE html>
<html>
<head>
<title>Welcome Email </title>
</head>
<body>
<h1>Welcome, {d.user.firstName} {d.user.lastName}! </h1>
<p>Thank you for registering with us. </p>
<p>Your email address is: {d.user.email} </p>
<p>Your membership level: {d.membershipLevel} </p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Welcome Email</title>
</head>
<body>
<h1>Welcome, John Doe!</h1>
<p>Thank you for registering with us.</p>
<p>Your email address is: john.doe@carbone.io</p>
<p>Your membership level: Premium </p>
</body>
</html>
Loops
Loops in Carbone allow you to repeat a section of your template for each item in an array from your JSON data. This is useful for generating lists, tables, images, or any repeated content dynamically.
A loop in Carbone requires two tags:
- Start Tag: Marks the beginning of the repeated block (e.g.,
{d.users[i].id}
). The i is the loop iterator (automatically managed by Carbone). - End Tag: Marks the end of the repeated block (e.g.,
{d.users[i+1]}
). The end tag i+1 does not refer to an actual array item but signals the end of the pattern.
All content (text, Carbone tags, HTML, and styles) between the start and end tags is repeated.
{
"users": [
{ "id": 1, "name": "Alice", "role": "Admin" },
{ "id": 2, "name": "Bob", "role": "Editor" },
{ "id": 3, "name": "Charlie", "role": "Viewer" }
]
}
<!DOCTYPE html>
<html>
<body>
<h1>User List</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<!-- Start of loop -->
<tr>
<td>{d.users[i].id}</td>
<td>{d.users[i].name}</td>
<td>{d.users[i].role}</td>
</tr>
<!-- End of loop -->
<tr>
<td>{d.users[i+1]}</td>
</tr>
</tbody>
</table>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<h1>User List</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Alice</td>
<td>Admin</td>
</tr>
<tr>
<td>2</td>
<td>Bob</td>
<td>Editor</td>
</tr>
<tr>
<td>3</td>
<td>Charlie</td>
<td>Viewer</td>
</tr>
</tbody>
</table>
</body>
</html>
Unlike traditional programming, Carbone loops do not require keywords like "for" or "foreach". The loop is defined implicitly by the tags.
Conditions
Three methods are available to conditionally show, hide, or style elements in your HTML templates. Each method is suited to different use cases, depending on the complexity of your conditions and the structure of your content:
- Inline CSS/HTML Conditions: Simple, and granular control over individual HTML/CSS elements. Use when you need to show/hide a single HTML element or CSS properties/attributes based on a data field.
- Smart conditions: Use
:drop()
or:keep()
formatters for removing or retaining entire elements, such as: tables, rows, or paragraphs. - Conditional Blocks: Use
:showBegin/showEnd
or:hideBegin/hideEnd
for showing or hiding large sections of content, including multiple elements, paragraphs, tables, or pages.
Inline HTML/CSS Conditions
Carbone allows you to dynamically inject CSS styles into your HTML templates using conditional logic and data fields. This is useful for showing/hiding elements or applying styles based on your dataset. Carbone supports the following conditional techniques:
- Inject CSS Values: Use Carbone’s inline conditions to dynamically set CSS property values (such as
display
,visibility
, oropacity
) based on your data. - Inject CSS Properties: You can inject entire CSS properties from your dataset.
- Inject Style Attribute: Inject a full style attribute from a data field.
- Inject HTML Blocks: Use the
:html
formatter to inject raw HTML strings from your dataset with conditions.
Inject CSS Values Example
In the following example, the display
, visibility
, and opacity
properties are conditionally set using Carbone tags:
- The <div> element is hidden if
d.showDiv
is false. - The <p> element is hidden if
d.showParagraph
is false. - The <span> element is invisible if
d.showSpan
is false.
{
"display": "none",
"showDiv": false,
"showParagraph": false,
"showSpan": false
}
<!DOCTYPE html>
<html>
<body>
<!-- Inject CSS values -->
<div style="display:{d.display};">This element is hidden and takes no space, only if 'showDiv' is 'true'.</div>
<!-- Inject CSS values based on conditions -->
<div style="display:{d.showDiv:ifEQ(true):show('block'):elseShow('none')};">This element is hidden and takes no space, only if 'showDiv' is 'false'.</div>
<p style="visibility:{d.showParagraph:ifEQ(true):show('visible'):elseShow('hidden')};"> This paragraph is hidden but occupies space, only if 'showParagraph' is 'false'.</p>
<span style="opacity:{d.showSpan:ifEQ(true):show('1'):elseShow('0')};">This element is invisible but still clickable, only if the 'showSpan' is 'false'.</span>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- Inject CSS values -->
<div style="display:none;">This element is hidden and takes no space, only if 'showDiv' is 'true'.</div>
<!-- Inject CSS values based on conditions -->
<div style="display:none;">This element is hidden and takes no space, only if 'showDiv' is 'true'.</div>
<p style="visibility:hidden;"> This paragraph is hidden but occupies space, only if 'showParagraph' is 'false'. </p>
<span style="opacity:0;">This element is invisible but still clickable, only if the 'showSpan' is 'false'.</span>
</body>
</html>
Inject CSS Properties Example
This example demonstrates how to dynamically inject entire CSS properties into an HTML element using Carbone tags. Two methods are available:
- Direct Injection: The first <img> tag injects the value of d.imageStyle directly into its style attribute.
- Conditional Injection: The second <img> tag uses a condition to determine which CSS property to apply, either the value of
d.imageStyle
or a static string "display:block".
{
"showImage": true,
"imageStyle": "display: none;"
}
<!DOCTYPE html>
<html>
<body>
<!-- Inject CSS properties -->
<img src="image.jpg" style="width: 150px;{d.imageStyle}border-radius: 8px;" alt="Hidden Image">
<!-- Inject CSS properties based on a condition -->
<img src="image.jpg" style="{d.showImage:ifEQ(true):show('display:block;'):elseShow(d.imageStyle)}" alt="Visible Image">
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- Inject CSS properties -->
<img src="image.jpg" style="width: 150px;display: none;border-radius: 8px;" alt="Hidden Image">
<!-- Inject CSS properties based on a condition -->
<img src="image.jpg" style="display:block;" alt="Visible Image">
</body>
</html>
Inject Style Attribute Example
This example shows how to inject an entire style attribute from your dataset into an HTML element.
- Direct Injection: The first button uses the style defined in
d.buttonStyles1
. - Conditional Injection: The second button applies the value of
d.buttonStyles1
ifd.buttonTheme
is "forest", otherwise it uses the value ofd.buttonStyles2
.
{
"buttonTheme": "ocean",
"buttonStyles1": "style="background-color: green;color: white;border: none;"",
"buttonStyles2": "style="background-color: black;color: red;border: 1px solid white;""
}
<!DOCTYPE html>
<html>
<body>
<!-- 3. Inject CSS Style Attribute -->
<button {d.buttonStyles1}>Click Me</button>
<!-- Inject CSS Style Attribute based on a condition -->
<button {d.buttonTheme:ifEQ('forest'):show(d.buttonStyles1):elseShow(d.buttonStyles2)}>Click Me</button>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- 3. Inject CSS Style attribute -->
<button style="background-color: green;color: white;border: none; >Click Me</button>
<!-- Inject CSS Style Attribute based on a condition -->
<button style="background-color: black;color: red;border: 1px solid white;">Click Me</button>
</body>
</html>
Inject HTML Block
This example demonstrates how to inject raw HTML blocks from your dataset into your template using conditions and the :html formatter.
- Direct Injection: The first line directly renders the HTML stored in
d.noteSection
. - Condtional Injection: The second line conditionally renders either
d.noteSection
ifd.displayNote
is true, ord.nothingSection
if false.
{
"displayNote": false,
"noteSection": "<div style='border-left: 3px solid #ff9800; padding: 8px;'><strong>Note:</strong> Maintenance at 2 AM UTC.</div>",
"nothingSection": "<strong style='text-align: center; padding: 10px; background: #f0f8ff;'>Nothing Significant To Report.</strong>"
}
<!DOCTYPE html>
<html>
<body>
<!-- Inject HTML Block -->
{d.noteSection:html}
<!-- Inject HTML Block based on a condition -->
{d.displayNote:ifEQ(true):show(d.noteSection):elseShow(d.nothingSection):html}
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- Inject HTML Block -->
<div style='border-left: 3px solid #ff9800; padding: 8px;'><strong>Note:</strong> Maintenance at 2 AM UTC.</div>
<!-- Inject HTML Block based on a condition -->
<strong style='text-align: center; padding: 10px; background: #f0f8ff;'>Nothing Significant To Report.</strong>
</body>
</html>
Drop / Keep
The :drop()
and :keep()
formatters allow you to conditionally remove or retain elements (such as tables, rows, or paragraphs) in your HTML templates. These formatters are especially useful for dynamic content generation, where you want to show or hide elements based on data conditions. Syntax:
- :drop(element) : Removes the element if the condition is true.
- :keep(element) : Retains the element if the condition is true.
Element | Description | Tag Position | Example |
---|---|---|---|
p | Drop/keep a paragraph | Within a paragraph | {d.text:ifEM:drop(p)} |
row | Drop/keep a table row | Inside a table cell | {d.condition:ifNE(value):keep(row)} |
table | Drop/keep an entire table | Within a table row | {d.condition:ifEQ(value):drop(table)} |
Notes
- For paragraphs and rows, you can specify a second parameter to drop/keep the next N elements (e.g.,
:drop(p, 3)
). - No Chaining: Do not chain other formatters after :drop() or :keep().
- HTML-Specific: Only table, row, and p elements are supported in HTML templates.
- Clean Output: The Carbone tag is removed from the final report.
Drop a Table Example
{
"showTable": false,
"list": [
{
"name": "Model 5"
},
{
"name": "Model 3"
},
{
"name": "Falcon Heavy"
}
]
}
<!DOCTYPE html>
<html>
<body>
<table>{d.showTable:ifEQ(false):drop(table)}
<tr><td>{d.list[i].name}</td></tr>
<tr><td>{d.list[i+1].name}</td></tr>
</table>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
</body>
</html>
Drop a Table Row Example
[
{ "name": "Falcon 9" },
{ "name": "Model 5" },
{ "name": "Model 3" },
{ "name": "Falcon Heavy" }
]
<!DOCTYPE html>
<html>
<body>
<table>
<tr><td>{d[i].name}{d[i].name:ifIN('Falcon'):drop(row)}</td></tr>
<tr><td>{d[i+1].name}</td></tr>
</table>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<table>
<tr><td>Model 5</td></tr>
<tr><td>Model 3</td></tr>
</table>
</body>
</html>
Drop a Paragraph Example
{ "text": "" }
<!DOCTYPE html>
<html>
<body>
<p>{d.text}{d.text:ifEM:drop(p, 2)}This paragraph and the next one will be dropped if 'text' is empty.</p>
<p>This paragraph will also be dropped.</p>
<p>This paragraph will remain.</p>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<p>This paragraph will remain.</p>
</body>
</html>
Conditional Sections
The pair of :showBegin/:showEnd
and :hideBegin/;hideEnd
formatters allow you to conditionally display a section of content in your HTML templates. These formatters are useful when you want to show/hide whole pages or groups of text, tables, or other elements based on data conditions. Syntax:
:showBegin
or:hideBegin
: Marks the start of a block to show/hide if the condition is true.:showEnd
orhideEnd
: Marks the end of the block.
showBegin / showEnd Example
The details section containing a list is hidden using the showBegin/showEnd
formatters, only if the showDetails
field is true
.
{
"showDetails": false,
"product": "Carbone Pro"
}
<!DOCTYPE html>
<html>
<body>
<p>Product: {d.product}</p>
{d.showDetails:ifEQ(true):showBegin}
<p>Details:</p>
<ul>
<li>Feature 1</li>
<li>Feature 2</li>
</ul>
{d.showDetails:ifEQ(true):showEnd}
<p>Thank you for using Carbone!</p>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<p>Product: Carbone Pro</p>
<p>Thank you for using Carbone!</p>
</body>
</html>
hideBegin / hideEnd Example
The greetings section is deleted when the field name
is undefined/null/empty
.
{
"name": null
}
<!DOCTYPE html>
<html>
<body>
<h2> Dashboard </h2>
{d.name:ifEM:hideBegin}
<strong style='margin: 0; font-size: 14px;'>
Welcome {d.name}!
</strong>
{d.name:ifEM:hideBegin}
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<h2> Dashboard </h2>
</body>
</html>
Pictures
Dynamic pictures allow you to inject images into your documents dynamically using data from your JSON input. For HTML templates, use the <img>
tag with the src attribute pointing to one of the following:
- Absolute URLs (e.g.,
https://carbone.io/img/carbone-logo.svg
). Carbone does not support relative paths (e.g.,/images/logo.png
or../assets/photo.jpg
). - Data-URIs (Base64 encoded, e.g.,
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD...
).
{
"userProfile": {
"name": "John Doe",
"profilePictureUrl": "https://carbone.io/images/john-doe.jpg",
"profilePictureBase64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD..."
}
}
<!DOCTYPE html>
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome, {d.userProfile.name}!</h1>
<div>
<img src="{d.userProfile.profilePictureUrl}" alt="Profile Picture" style="width:200px; height:auto;"/>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome, John Doe!</h1>
<div>
<img src="data:image/jpg...IMAGE BASE 64" alt="Profile Picture" style="width:200px; height:auto;"/>
</div>
</body>
</html>
To change the dimensions or scaling of an image, you can use HTML attributes or CSS styling for more control and responsiveness:
- Set fixed dimensions directly in the
<img>
tag, e.g.,<img src="{d.imageUrl}" width="300" height="200" alt="Dynamic Image">
. - Use CSS for sizing and changing aspect ratios. Inline styles can be used directly within your HTML tags:
<img src="{d.imageUrl}" style="width:300px; height:auto;" alt="Dynamic Image">
.
Charts
Use the :chart
formatter to dynamically inject charts into HTML templates: embbed a Carbone tag in the src attribute of an <img>
tag.
{
"chartOptions": {
"type": "echarts@v5a",
"width": 600,
"height": 400,
"theme": null,
"option": {
"xAxis": {
"type": "category",
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
"yAxis": {
"type": "value"
},
"series": [{
"data": [150, 230, 224, 218, 135, 147, 260],
"type": "line"
}]
}
}
}
<html>
<body>
<div class="chart-container">
<h2 class="chart-title">Sales Overview</h2>
<img src="{d.chartOptions:chart}" alt="Chart Image" width="600" height="400">
</div>
</body>
</html>
<html>
<body>
<div class="chart-container">
<h2 class="chart-title">Sales Overview</h2>
<img src="data:image/svg+xml CHART BASE 64" alt="Chart Image" width="600" height="400">
</div>
</body>
</html>
In this example, the {d.chartOptions:chart}
tag is replaced with an SVG image of the chart, which is dynamically generated based on the data provided in your dataset.
Key points:
- Supported ECharts Version: Carbone supports echarts@v5 (default) and echarts@v5a (optimized for SVG compatibility).
- Styling: Chart styling must be defined within the JSON dataset.
- No External Dependencies: Chart configuration does not support external dependencies (e.g., JS scripts).
- Dimensions: You can adjust the dimensions of the chart in two ways:
- Using the
<img>
Tag: Set the width and height attributes directly on the<img>
tag to control the size of the chart as it appears in the HTML document. - Using the EChart Configuration: Define the width and height within the EChart configuration object in your JSON dataset. This allows you to specify the dimensions programmatically.
- Using the
Colors
You can dynamically set or change CSS color properties in your HTML templates using Carbone tags. This is useful for theming, conditional styling, or personalization based on your dataset. Two Methods are available:
- Direct Injection: Inject color values directly from your dataset into style attributes.
- Conditional Injection: Use Carbone’s
:ifEQ
,:show
, and:elseShow
to conditionally apply colors.
{
"theme": "dark",
"textColor": "#ffffff",
"bgColor": "#1a1a1a",
"alertColor": "#ff4444",
"isUrgent": true
}
<!DOCTYPE html>
<html>
<body>
<!-- Directly inject color values -->
<div style="color: {d.textColor}; background-color: {d.bgColor}; padding: 10px;">
This div uses colors from the dataset.
</div>
<!-- Conditionally apply colors -->
<p style="color: {d.isUrgent:ifEQ(true):show(d.alertColor):elseShow('#333333')};">
{d.isUrgent:ifEQ(true):show('Urgent message!'):elseShow('Normal message.')}
</p>
<!-- Apply colors based on a theme -->
<button style="
color: {d.theme:ifEQ('dark'):show('#ffffff'):elseShow('#000000')};
background-color: {d.theme:ifEQ('dark'):show('#333333'):elseShow('#ffffff')};
border: none;
padding: 8px 16px;
">
{d.theme:ifEQ('dark'):show('Dark Mode'):elseShow('Light Mode')}
</button>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<div style="color: #ffffff; background-color: #1a1a1a; padding: 10px;">
This div uses colors from the dataset.
</div>
<p style="color: #ff4444;">
Urgent message!
</p>
<button style="color: #ffffff; background-color: #333333; border: none; padding: 8px 16px;">
Dark Mode
</button>
</body>
</html>
Barcodes
Carbone supports barcode generation in HTML templates using the :barcode
formatter. This allows you to inject barcodes as SVG images directly into your documents. How It Works:
- Use the
:barcode
formatter in antag's src attribute.
- Specify the barcode type (e.g.,
qrcode
,code128
,ean13
). See the full list of supported barcode types here. - Optional - Adjust dimensions either via the
<img>
tag attributes or within the formatter.
{
"productCode": "123456789",
"qrData": "https://example.com/product/123456789"
}
<!DOCTYPE html>
<html>
<body>
<!-- QR Code (dimensions set via img tag) -->
<img src="{d.qrData:barcode(qrcode)}" alt="QR Code" width="200" height="200">
<!-- EAN-13 Barcode (dimensions set via formatter) -->
<img src="{d.productCode:barcode(ean13, 'width:200;height:100')}" alt="EAN-13 Barcode">
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- QR Code -->
<img src="data:image/svg+xml;base64,...[SVG_DATA]..." alt="QR Code" width="200" height="200">
<!-- EAN-13 Barcode -->
<img src="data:image/svg+xml;base64,...[SVG_DATA]..." alt="EAN-13 Barcode">
</body>
</html>
Hyperlinks
You can dynamically set the href attribute of <a> tags using Carbone tags. This is useful for generating links based on your dataset, such as personalized URLs.
{
"documentationUrl": "https://carbone.io/documentation/",
"isLoggedIn": true,
"profileUrl": "https://account.carbone.io/",
"defaultUrl": "https://account.carbone.io/login",
"product": {
"name": "Carbone Cloud",
"url": "https://carbone.io/pricing.html"
}
}
<!DOCTYPE html>
<html>
<body>
<!-- Directly inject a URL -->
<a href="{d.documentationUrl}">Read the Docs</a>
<!-- Conditionally set a URL -->
<a href="{d.isLoggedIn:ifEQ(true):show(d.profileUrl):elseShow(d.defaultUrl)}">
{d.isLoggedIn:ifEQ(true):show('Your Profile'):elseShow('Login')}
</a>
<!-- Inject a URL from a nested object -->
<a href="{d.product.url}">Learn about {d.product.name}</a>
<!-- Combine static and dynamic paths -->
<a href="/docs/{d.product.name:lowerCase():replace(' ', '-')}">Documentation</a>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<a href="https://carbone.io/documentation/">Read the Docs</a>
<a href="https://account.carbone.io/">Your Profile</a>
<a href="https://carbone.io/pricing.html">Learn about Carbone Cloud</a>
<a href="/docs/carbone-cloud">Documentation</a>
</body>
</html>
Inject HTML in HTML
Carbone allows you to inject raw HTML strings from your dataset into your templates using the :html formatter. Without it, <
and >
characters are automatically encoded as <
and >
, which prevents the HTML from being rendered as markup.
{
"welcomeMessage": "<strong>Welcome!</strong> Here’s your dashboard.",
"alertMessage": "<div class='alert'>⚠️ Maintenance at 2 AM UTC.</div>",
"isAdmin": true,
"adminPanel": "<a href='/admin'>Go to Admin Panel</a>",
"userPanel": "<a href='/profile'>Go to Profile</a>"
}
<!DOCTYPE html>
<html>
<body>
<!-- Without :html (HTML is escaped) -->
<p>{d.welcomeMessage}</p>
<!-- With :html (HTML is rendered) -->
<p>{d.welcomeMessage:html}</p>
<!-- Conditional HTML injection -->
{d.isAdmin:ifEQ(true):show(d.adminPanel):elseShow(d.userPanel):html}
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<!-- Escaped HTML (displayed as text) -->
<p><strong>Welcome!</strong> Here’s your dashboard.</p>
<!-- Rendered HTML -->
<p><strong>Welcome!</strong> Here’s your dashboard.</p>
<!-- Conditionally injected HTML -->
<a href='/admin'>Go to Admin Panel</a>
</body>
</html>
Page Breaks
To insert a page break in PDFs generated from HTML templates, first define the following CSS class in your template’s <style>
section:
.page-break {
page-break-before: always;
break-before: page;
}
Then, insert a <div>
or <p>
with the page-break class where you want the new page to start:
<div>Page 1 content</div>
<p class="page-break"></p>
<div>Page 2 content</div>
Note: It works only for PDF output (ignored in HTML).
Page Formats
By default, Carbone generates PDF document in the A4
format.
Insert the <carbone-pdf-options>
custom element in the HTML template, and use the paper-size option to specify standard page sizes:
Value | Description |
---|---|
A0 , A1 , A2 , A3 , A4 , A5 , A6 |
ISO A-series paper sizes |
Letter |
US Letter (8.5 × 11 in) |
Legal |
US Legal (8.5 × 14 in) |
Tabloid |
Tabloid (11 × 17 in) |
Ledger |
Ledger (17 × 11 in) |
Note: Additional PDF Convertion options (margins, scaling, headers/footers, etc.) are available.
Example
This sets the PDF to A3 size in landscape orientation.
<carbone-pdf-options paper-size="A3" landscape="true" />
Headers Footers
Carbone allows you to define custom headers and footers for PDF documents generated from HTML templates.
Custom Elements
<carbone-pdf-header>
: Defines the header for every page (e.g. header example).<carbone-pdf-footer>
: Defines the footer for every page (e.g. footer example).
Key Features
- Include static text, dynamic content (using Carbone tags), and page numbers.
- For page numbering, use:
<span class="pageNumber"></span>
for the current page.<span class="totalPages"></span>
for the total pages.
- Insert only Inline CSS because external stylesheets are not supported.
- Headers and footers are PDF-only and are ignored in HTML output.
- Elements render in PDF even if hidden or commented out in the HTML template.
Custom Header Example
This example demonstrates a custom PDF header with dynamic content:
- Displays a centered title (Company Report | Q3 Financials).
- Shows the current date (Generated: 2025-10-17) using Carbone's built-in
{c.now}
chained with:formatDate('YYYY-MM-DD')
to format dates. - Includes the user's name (User: John Doe) from the dataset.
{
"reportTitle": "Q3 Financials",
"user": { "name": "John Doe" }
}
<carbone-pdf-header>
<div style="font-size: 12px; text-align: center; width: 100%;">
<span>Company Report | {d.reportTitle}</span>
<span>Generated: {c.now:formatDate('YYYY-MM-DD')}</span>
<span>User: {d.user.name}</span>
</div>
</carbone-pdf-header>
<carbone-pdf-header>
<div style="font-size: 12px; text-align: center; width: 100%;">
<span>Company Report | Q3 Financials</span>
<span>Generated: 2025-10-17</span>
<span>User: John Doe</span>
</div>
</carbone-pdf-header>
Custom Footer Example
This example demonstrates a custom PDF footer with:
- Page numbering (e.g., "Page 5 of 10") using
<span class="pageNumber"></span>
and<span class="totalPages"></span>
. - Dynamic copyright text injected from the dataset (
d.year
andd.company
).
{
"year": "2025",
"company": "Acme Inc"
}
<carbone-pdf-footer>
<div style="font-size: 10px; text-align: center; width: 100%;">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
<div style="font-size: 9px; text-align: right;">
© {d.year} {d.company}. All rights reserved.
</div>
</carbone-pdf-footer>
<carbone-pdf-footer>
<div style="font-size: 10px; text-align: center; width: 100%;">
Page 5 of 10
</div>
<div style="font-size: 9px; text-align: right;">
© 2025 Acme Inc. All rights reserved.
</div>
</carbone-pdf-footer>
Convert HTML to PDF
To generate a PDF from an HTML template using the Carbone API, follow this workflow:
- Prepare Two Files: Create an HTML Template (with Carbone tags e.g.
{d.name}
) and a JSON dataset to populate the template. - Generate a PDF, You have three options::
- Use the official Carbone integrations for platforms like N8N, Make, Zapier, Airtable, or Bubble.
- Or, Use one of the Carbone SDKs (Node.js, Go, Python, Java, JavaScript, or PHP).
- Or, Send a
POST /render/template
HTTP request to the Carbone API. Here’s an example using curl:
curl -X POST https://api.carbone.io/render/template?download=true \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "carbone-version: 5" \
-d '{
"template": "YOUR_HTML_TEMPLATE_AS_BASE64_STRING",
"data": {
"name": "John Doe"
},
"convertTo": "pdf",
"converter": "C"
}'
Key Parameters
Parameter | Description |
---|---|
template |
Your HTML template, encoded as a Base64 string. |
data |
JSON dataset used to populate the template. |
convertTo |
Must be set to "pdf". |
converter |
Must be set to "C". |
?download=true |
Query parameter to download the document as a stream. |
Authorization |
Header required for the Carbone Cloud API. Get your API key here. |
For more details, refer to the Carbone API Documentation.
PDF Conversion Options
Customize the PDF document by inserting the <carbone-pdf-options/>
element in the HTML template, and provide options as attribute.
Example
This configures the PDF to use A3 size, landscape orientation, a 2.5-inch bottom margin, and disables background printing.
<carbone-pdf-options
paper-size="A3"
landscape="true"
margin-bottom="2.5"
print-background="false"
/>
Available Options
Option | Type | Description |
---|---|---|
landscape |
boolean | Paper orientation. Defaults to false . |
display-header-footer |
boolean | Display header and footer. Defaults to false , or true if header/footer is provided |
print-background |
boolean | Print background graphics. Defaults to true . |
scale |
number | Scale of the webpage rendering. Defaults to 1 . |
paper-size |
string | Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6 (Default: A4) |
paper-width |
number | Overwrite Paper width in inches. Defaults to 8.27 inches (Default: A4) |
paper-height |
number | Overwrite Paper height in inches. Defaults to 11.7 inches (Default: A4) |
margin-top |
number | Overwrite Top margin in inches. Defaults to 0.5 inches. |
margin-bottom |
number | Overwrite Bottom margin in inches. Defaults to 0.5 inches. |
margin-left |
number | Overwrite Left margin in inches. Defaults to 0.5 inches. |
margin-right |
number | Overwrite Right margin in inches. Defaults to 0.5 inches. |
page-ranges |
string | Paper ranges to print, e.g., 1-5, 8, 11-13 . Pages are printed in document order. No page appears more than once. Empty string prints entire document. Invalid ranges are ignored. An error is thrown if the start page is greater than the end page. |
prefer-css-page-size |
boolean | Prefer CSS-defined page size. Defaults to false , in which case the content will be scaled to fit the paper size |