HTML to PDF examples
View SourceThese examples show common NativeElixirPdfUtilities.HtmlToPdf workflows. See
HTML to PDF compatibility for the supported
HTML, CSS, options, and known limits.
Render HTML
render/2 returns PDF bytes:
alias NativeElixirPdfUtilities.HtmlToPdf
html = """
<style>
@page { size: A4; margin: 18mm; }
body { font-family: "DejaVu Sans"; font-size: 10pt; }
h1 { border-bottom: 2pt solid #22344a; padding-bottom: 6pt; }
table { width: 100%; border-collapse: collapse; }
th, td { border: 1pt solid #d3d3d3; padding: 5pt; }
th { background-color: #eeeeee; text-align: left; }
.amount { text-align: right; }
</style>
<h1>Invoice INV-0001</h1>
<table>
<thead>
<tr><th>Item</th><th>Description</th><th class="amount">Amount</th></tr>
</thead>
<tbody>
<tr><td>PO-1</td><td>Cutting and sewing</td><td class="amount">120.00</td></tr>
<tr><td>PO-2</td><td>Finishing</td><td class="amount">80.00</td></tr>
</tbody>
</table>
"""
{:ok, pdf} = HtmlToPdf.render(html)
File.write!("/tmp/invoice.pdf", pdf)Render a file
render_file/3 reads the HTML and writes the PDF:
:ok =
HtmlToPdf.render_file(
"priv/static/templates/invoice.html",
"/tmp/invoice.pdf",
page_size: :a4,
margin: "18mm",
stylesheets: [{:file, "priv/static/templates/invoice.css"}],
base_url: "priv/static"
)Use {:css, css} for inline CSS and {:file, path} for a stylesheet file.
Add headers, footers, and page numbers
Page furniture is opt-in. Reserve page margins large enough for it:
{:ok, pdf} =
HtmlToPdf.render(
"<h1>Account statement</h1><p>Statement content...</p>",
margin: "18mm",
page_furniture: [
header: [
default: "<div style=\"font-size: 8pt\">Account statement</div>",
first: false
],
footer:
"<div style=\"font-size: 8pt; text-align: right\">" <>
"Page {{page}} of {{pages}}</div>"
]
)Use :first, :odd, :even, and :default variants when pages need
different furniture.
Load local images
Set :base_url when the document refers to local images or fonts. Referenced
paths must stay beneath that directory.
{:ok, pdf} =
HtmlToPdf.render(
"""
<div style="width: 90mm; border: 1pt solid #111; padding: 4mm">
<img src="images/product.png" alt="Product" style="width: 22mm">
<p>001764 - DEFAULT</p>
</div>
""",
base_url: "priv/static"
)To supply assets without filesystem access, map document references to bytes or trusted files:
HtmlToPdf.render(html,
assets: %{
"product-image" => {:bytes, png_bytes},
"report-font" => {:file, "priv/fonts/report-sans.ttf"}
}
)The HTML or CSS can use those exact references in src or url(...).
Register a font
Pass a static TrueType font when output must use the same face on every host:
{:ok, pdf} =
HtmlToPdf.render(
~s(<p style="font-family: 'Report Sans'">Café</p>),
fonts: [%{family: "Report Sans", path: "priv/fonts/report-sans.ttf"}]
)A document can also load a font beneath :base_url with @font-face:
{:ok, pdf} =
HtmlToPdf.render(
"""
<style>
@font-face {
font-family: "Report Sans";
src: url("fonts/report-sans.ttf") format("truetype");
}
body { font-family: "Report Sans"; }
</style>
<p>Café</p>
""",
base_url: "priv/static"
)Set PDF metadata
{:ok, pdf} =
HtmlToPdf.render(
"<title>Monthly statement</title><p>Statement content</p>",
metadata: [
author: "Finance Operations",
subject: "Customer statement",
keywords: ["statement", "monthly"],
creation_date: Date.utc_today()
]
)The first non-empty HTML <title> becomes the PDF title unless
metadata[:title] is set.
Render static form values
Form controls become visible, non-editable PDF content:
html = """
<input type="text" value="Amira Tan">
<input type="checkbox" checked>
<select><option selected>Approved</option></select>
<textarea>Documents verified</textarea>
<button type="button">Record application</button>
"""
{:ok, pdf} = HtmlToPdf.render(html)Handle an error
Rendering uses the library's shared diagnostic result:
case HtmlToPdf.render(html) do
{:ok, pdf} ->
File.write!("/tmp/document.pdf", pdf)
{:error, {reason, diagnostic}} ->
Logger.warning(
"PDF render failed with #{reason}: #{diagnostic.message}"
)
endUse the reason for program flow and the diagnostic for logs or template fixes. See Diagnostics for the full contract.