DEV Community

IronSoftware
IronSoftware

Posted on

Advanced HTML to PDF Techniques in C# (.NET Guide)

Once you've mastered basic HTML-to-PDF conversion, the next challenge is adding professional features: headers with page numbers, watermarks, digital signatures, responsive page layouts, and archival-quality PDFs.

I've implemented these features in production systems handling millions of PDFs. Here's how to go beyond the basics.

How Do I Add Headers and Footers with Page Numbers?

Headers and footers with dynamic content (page numbers, dates, titles) are essential for professional PDFs.

IronPDF makes this straightforward with merge fields:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <div style='text-align: center; font-size: 10px; color: #666;'>
            Confidential Document - {date}
        </div>"
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <div style='text-align: center; font-size: 10px; color: #666;'>
            Page {page} of {total-pages}
        </div>"
};

// Adjust margins to make room for headers/footers
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;

var pdf = renderer.RenderHtmlAsPdf("<h1>Document Content</h1>");
pdf.SaveAs("with-headers-footers.pdf");
Enter fullscreen mode Exit fullscreen mode

Supported merge fields:

  • {page}: Current page number
  • {total-pages}: Total page count
  • {date}: Current date
  • {time}: Current time
  • {url}: Source URL (if rendering from URL)
  • {html-title}: HTML <title> tag content
  • {pdf-title}: PDF metadata title

These placeholders are automatically replaced during rendering.

Can I Style Headers and Footers with CSS?

Yes. Headers and footers support full HTML and CSS:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <style>
            .header {
                display: flex;
                justify-content: space-between;
                padding: 10px 20px;
                border-bottom: 2px solid #2c3e50;
                font-family: Arial, sans-serif;
            }
            .logo { font-weight: bold; color: #2c3e50; }
            .date { color: #7f8c8d; font-size: 9px; }
        </style>
        <div class='header'>
            <span class='logo'>Company Name</span>
            <span class='date'>{date}</span>
        </div>"
};

renderer.RenderingOptions.MarginTop = 60;

var pdf = renderer.RenderHtmlAsPdf("<h1>Professional Document</h1>");
pdf.SaveAs("styled-header.pdf");
Enter fullscreen mode Exit fullscreen mode

IronPDF's dynamic margin sizing automatically adjusts content based on header/footer height.

How Do I Add Different Headers for First Page vs. Other Pages?

For cover pages or reports where the first page needs a different header, use conditional logic:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <style>
            .first-page { display: none; }
            .other-pages { display: block; }
        </style>
        <div class='first-page' style='text-align: center; font-size: 18px; font-weight: bold;'>
            Cover Page Header
        </div>
        <div class='other-pages' style='text-align: right; font-size: 9px;'>
            Page {page} of {total-pages}
        </div>"
};

renderer.RenderingOptions.FirstPageNumber = 1;
renderer.RenderingOptions.MarginTop = 40;

var pdf = renderer.RenderHtmlAsPdf("<h1>Cover Page</h1><div style='page-break-after: always;'></div><h2>Page 2</h2>");
pdf.SaveAs("different-first-page.pdf");
Enter fullscreen mode Exit fullscreen mode

You can also use IronPDF's ApplyStamp() method to overlay content on specific pages post-rendering.

How Do I Add Watermarks to PDFs?

Watermarks are useful for "DRAFT", "CONFIDENTIAL", or branding overlays.

Approach 1: Watermark during HTML rendering

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var html = @"
<style>
    body { position: relative; }
    .watermark {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(-45deg);
        font-size: 120px;
        color: rgba(0, 0, 0, 0.1);
        font-weight: bold;
        z-index: -1;
        user-select: none;
    }
</style>
<div class='watermark'>DRAFT</div>
<h1>Document Content</h1>
<p>This document has a watermark.</p>";

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("watermarked.pdf");
Enter fullscreen mode Exit fullscreen mode

Approach 2: Watermark after PDF generation

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Original Document</h1>");

// Apply watermark stamp to all pages
pdf.ApplyWatermark("<h1 style='color: rgba(255,0,0,0.3);'>CONFIDENTIAL</h1>",
    rotation: 45,
    opacity: 30);

pdf.SaveAs("watermark-stamp.pdf");
Enter fullscreen mode Exit fullscreen mode

The post-processing approach is better when you need to watermark existing PDFs or apply different watermarks conditionally.

How Do I Control Page Breaks Precisely?

CSS page break properties control where pages split:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var html = @"
<style>
    .section {
        page-break-after: always; /* Force page break after this element */
    }
    .keep-together {
        page-break-inside: avoid; /* Prevent breaking inside this element */
    }
    h1 {
        page-break-before: always; /* New page before every h1 */
    }
</style>

<div class='section'>
    <h2>Section 1</h2>
    <p>This section ends with a page break.</p>
</div>

<div class='keep-together'>
    <h3>Important Block</h3>
    <p>This entire block stays on one page—no splits.</p>
</div>

<h1>Chapter 2</h1>
<p>This starts on a new page because of the h1 rule.</p>";

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("controlled-breaks.pdf");
Enter fullscreen mode Exit fullscreen mode

Page break properties:

  • page-break-before: always — Start a new page before this element
  • page-break-after: always — Start a new page after this element
  • page-break-inside: avoid — Prevent splitting this element across pages

These work reliably with IronPDF's Chromium rendering.

Can I Use Responsive CSS for Different Page Sizes?

Yes. Use @media queries for print-specific styling:

using IronPdf;
using IronPdf.Rendering;
// Install via NuGet: Install-Package IronPdf

var html = @"
<style>
    @media print {
        .no-print { display: none; }
        .print-only { display: block; }
        body { font-size: 12pt; }
    }
    @media screen {
        .print-only { display: none; }
    }
    @page {
        margin: 2cm;
    }
</style>

<div class='no-print'>
    <p>This appears in browsers but NOT in PDFs.</p>
</div>

<div class='print-only'>
    <p>This appears ONLY in PDFs.</p>
</div>

<h1>Document Title</h1>";

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("responsive.pdf");
Enter fullscreen mode Exit fullscreen mode

IronPDF respects CSS @media print rules, so you can design one HTML template that works for both web and PDF.

How Do I Generate Archival-Quality PDFs (PDF/A)?

PDF/A is an ISO-standardized format for long-term archival. It embeds all fonts and images and disallows features that may not render consistently decades from now.

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = false; // Required for PDF/A
renderer.RenderingOptions.CreatePdfFormsFromHtml = false;

var pdf = renderer.RenderHtmlAsPdf("<h1>Archival Document</h1>");

// Convert to PDF/A-2B
pdf.ToPdfA();

pdf.SaveAs("archive.pdf");
Enter fullscreen mode Exit fullscreen mode

PDF/A compliance ensures your PDFs remain readable for decades, even as software evolves.

Can I Add Digital Signatures to PDFs?

Yes. Digital signatures provide authenticity and tamper-evidence.

using IronPdf;
using IronPdf.Signing;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Contract Document</h1>");

// Load certificate (.pfx file)
var signature = new PdfSignature("certificate.pfx", "password");
signature.SigningContact = "legal@company.com";
signature.SigningReason = "Contract Approval";
signature.SigningLocation = "San Francisco, CA";

pdf.Sign(signature);
pdf.SaveAs("signed-contract.pdf");
Enter fullscreen mode Exit fullscreen mode

The PDF will display a signature badge in PDF readers. Recipients can verify the signature's authenticity using the certificate.

How Do I Add Form Fields to PDFs?

IronPDF can convert HTML form elements into interactive PDF forms:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var html = @"
<form>
    <label>Name:</label>
    <input type='text' name='name' />

    <label>Email:</label>
    <input type='email' name='email' />

    <label>Comments:</label>
    <textarea name='comments'></textarea>

    <label>Subscribe:</label>
    <input type='checkbox' name='subscribe' />
</form>";

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CreatePdfFormsFromHtml = true;

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("form.pdf");
Enter fullscreen mode Exit fullscreen mode

The generated PDF contains fillable form fields that users can complete in Adobe Reader or other PDF viewers.

How Do I Programmatically Fill PDF Forms?

If you have an existing PDF form, you can populate it programmatically:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("template-form.pdf");

var form = pdf.Form;
form.SetFieldValue("name", "John Doe");
form.SetFieldValue("email", "john@example.com");
form.SetFieldValue("subscribe", "true");

pdf.SaveAs("filled-form.pdf");
Enter fullscreen mode Exit fullscreen mode

This is useful for automated report generation where you fill templates with database data.

Can I Merge Multiple PDFs into One?

Yes, IronPDF can merge multiple PDFs:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var pdf3 = PdfDocument.FromFile("document3.pdf");

var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("combined.pdf");
Enter fullscreen mode Exit fullscreen mode

Or merge HTML-rendered PDFs:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

var coverPage = renderer.RenderHtmlAsPdf("<h1>Cover Page</h1>");
var contentPage = renderer.RenderHtmlAsPdf("<h1>Content</h1>");
var appendix = renderer.RenderHtmlAsPdf("<h1>Appendix</h1>");

var finalPdf = PdfDocument.Merge(coverPage, contentPage, appendix);
finalPdf.SaveAs("final-report.pdf");
Enter fullscreen mode Exit fullscreen mode

How Do I Split PDFs into Separate Files?

Extract specific pages from a PDF:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("large-document.pdf");

// Extract pages 1-5
var subset = pdf.CopyPages(0, 4); // Zero-indexed
subset.SaveAs("pages-1-to-5.pdf");

// Extract a single page
var singlePage = pdf.CopyPage(9); // Page 10 (zero-indexed)
singlePage.SaveAs("page-10.pdf");
Enter fullscreen mode Exit fullscreen mode

Can I Compress PDFs to Reduce File Size?

Yes. IronPDF supports compression:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Document with Images</h1><img src='large-image.jpg'>");

// Compress images and optimize file size
pdf.CompressImages(90); // 90% quality
pdf.CompressionStrategy = PdfCompressionStrategy.HighQuality;

pdf.SaveAs("compressed.pdf");
Enter fullscreen mode Exit fullscreen mode

Compression is especially useful for PDFs with many images.

How Do I Add Metadata (Title, Author, Subject)?

Set PDF metadata for better organization and searchability:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Annual Report 2025</h1>");

pdf.MetaData.Title = "Annual Report 2025";
pdf.MetaData.Author = "Jacob Mellor";
pdf.MetaData.Subject = "Financial Performance";
pdf.MetaData.Keywords = "finance, report, 2025";
pdf.MetaData.CreationDate = DateTime.Now;

pdf.SaveAs("annual-report-2025.pdf");
Enter fullscreen mode Exit fullscreen mode

Metadata appears in PDF reader properties and helps with document management systems.

Can I Password-Protect PDFs?

Yes, encrypt PDFs with user and owner passwords:

using IronPdf;
using IronPdf.Engines.Chrome;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential Document</h1>");

// Set passwords
pdf.Password = "user-password"; // Required to open the PDF
pdf.OwnerPassword = "owner-password"; // Required to change permissions

// Set permissions (what users can do with the PDF)
pdf.SecuritySettings.AllowUserCopying = false;
pdf.SecuritySettings.AllowUserPrinting = false;
pdf.SecuritySettings.AllowUserAnnotations = false;
pdf.SecuritySettings.AllowUserFormData = false;
pdf.SecuritySettings.AllowUserModifyDocument = false;

pdf.SaveAs("encrypted.pdf");
Enter fullscreen mode Exit fullscreen mode

Users must enter the password to open or modify the PDF.

How Do I Extract Text from Existing PDFs?

IronPDF can parse and extract text from PDFs:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("document.pdf");

// Extract all text
string allText = pdf.ExtractAllText();
Console.WriteLine(allText);

// Extract text from specific page
string pageText = pdf.ExtractTextFromPage(0); // First page (zero-indexed)
Console.WriteLine(pageText);
Enter fullscreen mode Exit fullscreen mode

Useful for indexing PDFs or extracting data for processing.

Can I Add Bookmarks (Table of Contents)?

Yes, create PDF bookmarks for navigation:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(@"
<h1 id='chapter1'>Chapter 1</h1>
<p>Content for chapter 1...</p>
<div style='page-break-after: always;'></div>

<h1 id='chapter2'>Chapter 2</h1>
<p>Content for chapter 2...</p>");

// Add bookmarks
pdf.Bookmarks.Add("Chapter 1", 0); // Page 1 (zero-indexed)
pdf.Bookmarks.Add("Chapter 2", 1); // Page 2

pdf.SaveAs("with-bookmarks.pdf");
Enter fullscreen mode Exit fullscreen mode

Bookmarks appear in the PDF reader's sidebar for easy navigation.

How Do I Render Charts and Graphs from JavaScript Libraries?

IronPDF executes JavaScript before rendering, so libraries like Chart.js work:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var html = @"
<!DOCTYPE html>
<html>
<head>
    <script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
</head>
<body>
    <canvas id='myChart' width='400' height='200'></canvas>
    <script>
        const ctx = document.getElementById('myChart').getContext('2d');
        new Chart(ctx, {
            type: 'bar',
            data: {
                labels: ['Q1', 'Q2', 'Q3', 'Q4'],
                datasets: [{
                    label: 'Revenue',
                    data: [12, 19, 3, 5]
                }]
            }
        });
    </script>
</body>
</html>";

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RenderDelay = 1000; // Wait for Chart.js to render
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("chart.pdf");
Enter fullscreen mode Exit fullscreen mode

The rendered PDF includes the chart as a rasterized image.

Advanced Rendering Options Reference

Here's a quick reference for advanced rendering options:

using IronPdf;
using IronPdf.Rendering;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

// Page settings
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 40;
renderer.RenderingOptions.MarginBottom = 40;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;

// Rendering quality
renderer.RenderingOptions.Dpi = 300;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;

// JavaScript and timing
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.RenderDelay = 500; // Wait 500ms before rendering
renderer.RenderingOptions.Timeout = 60; // Timeout after 60 seconds

// Forms and interactivity
renderer.RenderingOptions.CreatePdfFormsFromHtml = true;

// Advanced
renderer.RenderingOptions.ViewPortWidth = 1024;
renderer.RenderingOptions.ViewPortHeight = 768;
renderer.RenderingOptions.Zoom = 100; // 100% zoom

var pdf = renderer.RenderHtmlAsPdf("<h1>Advanced PDF</h1>");
pdf.SaveAs("advanced.pdf");
Enter fullscreen mode Exit fullscreen mode

These options give you fine-grained control over PDF output.


Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)