Skip to main content Link Search Menu Expand Document (external link)

HTML to PDF

Understand how HTML elements translate to PDF documents and what’s different from browser rendering.


Learning Objectives

By the end of this article, you’ll be able to:

  • Understand which HTML elements Scryber supports
  • Recognize differences between browser and PDF rendering
  • Avoid common HTML-to-PDF pitfalls
  • Structure HTML documents optimally for PDFs

Supported HTML Elements

Scryber supports a comprehensive subset of HTML5 elements:

Document Structure

Element Supported Notes
<html> Root element (with or without namespace)
<head> Contains metadata and styles
<body> Main content container
<title> Sets PDF document title
<style> Embedded CSS
<link> External stylesheets (rel=”stylesheet”)
<meta> Document metadata

Text Content

Element Supported Notes
<h1> to <h6> Headings with hierarchy
<p> Paragraphs
<div> Generic container
<span> Inline container
<br> Line break
<hr> Horizontal rule
<pre> Preformatted text
<blockquote> Block quotation

Lists

Element Supported Notes
<ul> Unordered list
<ol> Ordered list
<li> List item
<dl> Definition list
<dt> Definition term
<dd> Definition description

Tables

Element Supported Notes
<table> Table container
<thead> Table header
<tbody> Table body
<tfoot> Table footer
<tr> Table row
<th> Header cell
<td> Data cell
<colgroup> Column group
<col> Column definition

Text Formatting

Element Supported Notes
<strong>, <b> Bold text
<em>, <i> Italic text
<u> Underlined text
<s>, <del> Strikethrough
<mark> Highlighted text
<small> Smaller text
<sup> Superscript
<sub> Subscript
<code> Inline code
<kbd> Keyboard input
Element Supported Notes
<a> Hyperlinks (internal and external)
<img> Images (PNG, JPEG, GIF, SVG)
<svg> Inline SVG graphics

Forms (Display Only)

Element Supported Notes
<form> Form container (visual only)
<input> Input fields (visual representation)
<textarea> Text area (visual)
<select> Dropdown (visual)
<button> Button (visual)
<label> Form label

Semantic Elements

Element Supported Notes
<header> Header section
<footer> Footer section
<section> Document section
<article> Article content
<aside> Sidebar content
<nav> Navigation
<main> Main content

Special Scryber Elements

Element Purpose
<page-number /> Current page number
<page-count /> Total page count
<template> Data binding iteration
<var> Variable storage
<if>, <unless> Conditional rendering
<frameset>, <frame> PDF merging
<object> File attachments

NOT Supported (Browser-Specific)

These elements don’t make sense in PDF context:

Element Why Not Supported
<script> No JavaScript execution in PDFs
<canvas> Use SVG instead
<video>, <audio> No media playback in static PDFs
<iframe> Limited support (use for content inclusion only)
Flexbox Use tables or absolute positioning
CSS Grid Use tables or absolute positioning
CSS Animations PDFs are static
CSS Transitions PDFs are static

Key Differences from Browser Rendering

1. Page-Based Layout

Browser: Continuous scrolling PDF: Fixed-size pages with page breaks

<style>
    /* Force page break before element */
    .new-section {
        page-break-before: always;
    }

    /* Avoid breaking inside element */
    .keep-together {
        page-break-inside: avoid;
    }
</style>

<div class="new-section">
    <h1>Chapter 2</h1>
    <p>This starts on a new page.</p>
</div>

2. Print Units (Points)

Browser: Pixels (px) - screen-based PDF: Points (pt) - print-based (72pt = 1 inch)

/* Prefer points for PDFs */
body {
    font-size: 11pt;  /* ✓ Recommended */
    margin: 40pt;     /* ✓ Recommended */
}

/* Pixels work but convert to points */
body {
    font-size: 14px;  /* Converts to ~10.5pt */
}

3. No Dynamic Content

Browser: Interactive JavaScript PDF: Static output

<!-- ❌ Won't work in PDF -->
<button onclick="alert('Hello')">Click Me</button>

<!-- ✓ Use data binding instead -->
<p></p>

4. Font Handling

Browser: Uses system fonts PDF: Fonts must be embedded or use standard PDF fonts

/* Standard PDF fonts (always available) */
body {
    font-family: Helvetica, Arial, sans-serif;
}

/* Custom fonts must be loaded */
@font-face {
    font-family: 'CustomFont';
    src: url('./fonts/CustomFont.ttf');
}

5. Image Loading

Browser: Lazy loading, async PDF: All images loaded before generation

<!-- Images must be accessible at generation time -->
<img src="./images/logo.png" />
<img src="https://example.com/image.jpg" />

6. Fixed Page Dimensions

Browser: Responsive, fluid width PDF: Fixed page size (e.g., 8.5” × 11”)

@page {
    size: Letter;  /* 8.5in × 11in */
    margin: 1in;
}

/* Percentages relative to page width */
.container {
    width: 100%;  /* Full page width minus margins */
}

HTML Document Structure for PDFs

Minimal Valid Document

<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
    <title>Document Title</title>
</head>
<body>
    <p>Content</p>
</body>
</html>
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
    <title>Professional Document</title>
    <meta charset="UTF-8" />
    <meta name="author" content="Your Name" />
    <meta name="subject" content="Document Subject" />

    <style>
        /* Page setup */
        @page {
            size: Letter;
            margin: 1in;
        }

        /* Base styles */
        body {
            font-family: 'Helvetica', sans-serif;
            font-size: 11pt;
            color: #333;
            line-height: 1.6;
        }

        /* Headers */
        h1, h2, h3 {
            color: #2563eb;
        }
    </style>
</head>
<body>
    <!-- Header (optional) -->
    <header>
        <h1>Document Title</h1>
    </header>

    <!-- Main content -->
    <main>
        <section>
            <h2>Section 1</h2>
            <p>Content here.</p>
        </section>

        <section>
            <h2>Section 2</h2>
            <p>More content.</p>
        </section>
    </main>

    <!-- Footer (optional) -->
    <footer style="position: fixed; bottom: 0; width: 100%; text-align: center;">
        Page <page-number /> of <page-count />
    </footer>
</body>
</html>

Common HTML Patterns

1. Two-Column Layout

<style>
    .two-column {
        display: table;
        width: 100%;
    }
    .column {
        display: table-cell;
        width: 50%;
        padding: 10pt;
    }
</style>

<div class="two-column">
    <div class="column">
        <h3>Left Column</h3>
        <p>Content here.</p>
    </div>
    <div class="column">
        <h3>Right Column</h3>
        <p>Content here.</p>
    </div>
</div>
<style>
    .header {
        display: table;
        width: 100%;
        border-bottom: 2pt solid #2563eb;
        padding-bottom: 10pt;
        margin-bottom: 20pt;
    }
    .logo {
        display: table-cell;
        width: 100pt;
    }
    .title {
        display: table-cell;
        vertical-align: middle;
        padding-left: 20pt;
    }
</style>

<div class="header">
    <div class="logo">
        <img src="logo.png" style="width: 80pt;" />
    </div>
    <div class="title">
        <h1>Company Name</h1>
        <p>Document Title</p>
    </div>
</div>

3. Info Box

<style>
    .info-box {
        border: 1pt solid #2563eb;
        border-left: 4pt solid #2563eb;
        background-color: #eff6ff;
        padding: 15pt;
        margin: 15pt 0;
    }
</style>

<div class="info-box">
    <strong>Important:</strong> This is an informational callout.
</div>

4. Styled Table

<style>
    table {
        width: 100%;
        border-collapse: collapse;
        margin: 20pt 0;
    }
    th {
        background-color: #2563eb;
        color: white;
        padding: 10pt;
        text-align: left;
    }
    td {
        padding: 8pt;
        border-bottom: 1pt solid #e5e7eb;
    }
    tr:nth-child(even) {
        background-color: #f9fafb;
    }
</style>

<table>
    <thead>
        <tr>
            <th>Item</th>
            <th>Description</th>
            <th>Price</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Product A</td>
            <td>Description</td>
            <td>$100.00</td>
        </tr>
        <tr>
            <td>Product B</td>
            <td>Description</td>
            <td>$200.00</td>
        </tr>
    </tbody>
</table>

Testing HTML for PDF Compatibility

Browser Preview Method

  1. Open your HTML in a browser
  2. Use Print Preview (Ctrl+P / Cmd+P)
  3. Check how content flows across pages
  4. Note any page break issues

Limitations: Browser print preview doesn’t perfectly match Scryber output

Scryber Testing Method

public void TestTemplate(string htmlPath)
{
    try
    {
        var doc = Document.ParseDocument(htmlPath);

        using (var ms = new MemoryStream())
        {
            doc.SaveAsPDF(ms);
            Console.WriteLine($"✓ Valid: {htmlPath} ({ms.Length} bytes)");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"✗ Error in {htmlPath}: {ex.Message}");
    }
}

Common Pitfalls

❌ Using Unsupported CSS

<style>
    .container {
        display: flex;  /* Not supported */
        display: grid;  /* Not supported */
    }
</style>

Solution: Use tables or absolute positioning

<style>
    .container {
        display: table;
        width: 100%;
    }
    .item {
        display: table-cell;
    }
</style>

❌ Assuming JavaScript Works

<script>
    // This won't execute in PDFs
    document.getElementById('date').innerText = new Date();
</script>

Solution: Use data binding

<p>Date: {{model.currentDate}}</p>

❌ Relative URLs Without Base

<!-- May not resolve correctly -->
<img src="../images/logo.png" />

Solution: Use absolute paths or set base

<head>
    <base href="https://example.com/" />
</head>
<body>
    <img src="images/logo.png" />
</body>

Try It Yourself

Exercise 1: Element Test

Create an HTML document using at least 10 different HTML elements from the supported list. Generate a PDF and verify all elements render correctly.

Exercise 2: Browser vs PDF

Open one of your HTML templates in a browser and compare it to the PDF output. Note the differences.

Exercise 3: Unsupported Element Test

Try using an unsupported element (like <canvas>) and observe the result. How does Scryber handle it?


Next Steps

Now that you understand HTML-to-PDF conversion:

  1. CSS Basics - Learn CSS styling for PDFs
  2. Pages & Sections - Master multi-page documents
  3. HTML Element Reference - Complete element documentation

Additional Resources


Continue learning → CSS Basics