DEV Community

IronSoftware
IronSoftware

Posted on

PDF Rendering Options in C# (.NET Tutorial)

Default PDF rendering settings are fine until they're not. I discovered this when a client complained that our generated reports had headers overlapping content, page breaks cutting through tables, and backgrounds missing from printed output.

The issue wasn't the HTML—it rendered perfectly in browsers. The problem was PDF rendering configuration. Here's how I fixed it.

What Are PDF Rendering Options?

Rendering options control how HTML/CSS converts to PDF. They define margins, paper size, orientation, headers, footers, JavaScript execution, and dozens of other parameters that affect the final PDF output.

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

var renderer = new [ChromePdfRenderer](https://ironpdf.com/blog/videos/how-to-render-webgl-sites-to-pdf-in-csharp-ironpdf/)();
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");
Enter fullscreen mode Exit fullscreen mode

Without configuring rendering options, you get Chrome's default PDF print settings, which may not match your requirements.

Why Do Rendering Options Matter?

Browsers and PDF rendering engines have different defaults. A webpage that looks great in Chrome can break in PDF form because:

  • Margins: Browsers use screen margins (usually 0), while PDFs need print margins
  • Page breaks: Browsers paginate dynamically; PDFs use fixed page dimensions
  • Backgrounds: CSS backgrounds often don't print by default
  • JavaScript: Dynamic content needs execution time before rendering

I spent hours debugging layout issues before realizing the root cause was rendering configuration, not my HTML.

How Do I Set Page Margins?

Margins create whitespace around page edges. They're critical for print-friendly PDFs and preventing content from bleeding to page edges.

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 25;
renderer.RenderingOptions.MarginLeft = 20;
renderer.RenderingOptions.MarginRight = 20;

var pdf = renderer.RenderHtmlAsPdf("<h1>Report Title</h1>");
pdf.SaveAs("report.pdf");
Enter fullscreen mode Exit fullscreen mode

Margins are measured in millimeters by default. For invoices and contracts, I typically use 20-25mm margins to leave room for binding or hole punching.

What Paper Sizes Are Available?

IronPDF supports standard paper sizes via the PdfPaperSize enum: A4, Letter, Legal, A3, Tabloid, and more.

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;

var pdf = renderer.RenderHtmlAsPdf("<table>...</table>");
pdf.SaveAs("landscape-table.pdf");
Enter fullscreen mode Exit fullscreen mode

For wide tables or charts, landscape orientation prevents horizontal scrolling or content truncation.

How Do I Set Custom Paper Dimensions?

When standard sizes don't fit, define custom dimensions:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.SetCustomPaperSizeinMillimeters(200, 300);

var pdf = renderer.RenderHtmlAsPdf("<div>Custom Size</div>");
pdf.SaveAs("custom.pdf");
Enter fullscreen mode Exit fullscreen mode

I used this for shipping labels (100mm x 150mm) where standard sizes wasted material.

Why Don't Backgrounds Appear in My PDF?

By default, Chrome's print engine excludes CSS backgrounds to save ink. Enable PrintHtmlBackgrounds to include them:

using IronPdf;

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

var html = @"
<style>
  body { background-color: lightblue; }
  .highlight { background-color: yellow; }
</style>
<div class='highlight'>Important Text</div>";

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

Without this setting, background colors and images vanish in the PDF output, breaking designs that rely on colored sections or watermarks.

How Do I Add Headers and Footers?

Headers and footers appear on every page. They're useful for page numbers, document titles, or company branding.

using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center'>Monthly Report - {page} of {total-pages}</div>"
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right'>Confidential</div>"
};

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

The {page} and {total-pages} placeholders auto-populate with the current page number and total page count. I also use {date}, {time}, and {url} for dynamic headers.

What If JavaScript Modifies My HTML Before Rendering?

Enable JavaScript execution and set a timeout to allow scripts to finish:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.RenderDelay = 500; // Wait 500ms for JavaScript

var html = @"
<div id='content'>Loading...</div>
<script>
  setTimeout(() => {
    document.getElementById('content').innerText = 'Data Loaded!';
  }, 300);
</script>";

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

Without EnableJavaScript, the PDF would show "Loading..." because the script never ran. The RenderDelay ensures IronPDF waits for async operations to complete.

How Do I Control Page Breaks?

CSS page-break properties work in PDF rendering:

var html = @"
<style>
  .page-break { page-break-after: always; }
  .no-break { page-break-inside: avoid; }
</style>

<div class='page-break'>Page 1</div>
<div>Page 2</div>

<table class='no-break'>
  <tr><td>Table won't split</td></tr>
</table>";

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

The page-break-after: always forces content onto a new page. The page-break-inside: avoid prevents tables or sections from splitting across pages.

This solved my issue with tables being cut mid-row.

How Do I Change CSS Media Type?

CSS media queries behave differently for screen vs print. Set the media type to match your stylesheets:

using IronPdf;
using IronPdf.Rendering;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;

var html = @"
<style>
  @media print {
    body { font-size: 12pt; }
  }
  @media screen {
    body { font-size: 16pt; }
  }
</style>
<body>Styled Content</body>";

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

Setting CssMediaType.Print activates @media print rules, which often hide navigation, adjust colors, and optimize layout for printing.

Can I Apply Custom CSS to Any HTML?

Yes, via CustomCssUrl. This is helpful for applying print styles to external HTML you don't control:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomCssUrl = "https://example.com/print-styles.css";

var pdf = renderer.RenderUrlAsPdf("https://example.com/article");
pdf.SaveAs("styled-article.pdf");
Enter fullscreen mode Exit fullscreen mode

I used this to add company branding (logo watermark, color scheme) to PDFs generated from third-party content.

How Do I Generate a Table of Contents?

IronPDF can auto-generate a table of contents from HTML headings:

using IronPdf;
using IronPdf.Rendering;

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

var html = @"
<h1>Chapter 1</h1>
<p>Content...</p>
<h1>Chapter 2</h1>
<p>More content...</p>";

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

The TOC appears at the start of the PDF with clickable links to each heading. This is useful for long reports or manuals.

What About Rendering Delays for Ajax Content?

If your HTML loads data via Ajax, increase RenderDelay to wait for the requests:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.RenderDelay = 2000; // Wait 2 seconds

var html = @"
<div id='data'>Loading...</div>
<script>
  fetch('/api/data')
    .then(r => r.text())
    .then(data => document.getElementById('data').innerText = data);
</script>";

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

Without sufficient delay, the PDF renders before Ajax completes, showing "Loading..." instead of actual data.

How Do I Force Grayscale Output?

Set GrayScale = true to convert colored content to black and white:

using IronPdf;

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

var html = "<div style='color:red'>Red Text</div>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("grayscale.pdf");
Enter fullscreen mode Exit fullscreen mode

This is useful for documents intended for black-and-white printing, reducing ink usage and ensuring readability without color.

Can I Set Viewport Size for Responsive Designs?

Yes, via ViewPortWidth and ViewPortHeight:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.ViewPortWidth = 1024;
renderer.RenderingOptions.ViewPortHeight = 768;

var pdf = renderer.RenderUrlAsPdf("https://responsive-site.com");
pdf.SaveAs("desktop-view.pdf");
Enter fullscreen mode Exit fullscreen mode

This controls the browser window size used during rendering, affecting how responsive CSS media queries trigger. For mobile-optimized PDFs, use smaller viewport dimensions like 375x667 (iPhone size).

How Do I Handle Rendering Timeouts?

Long-running JavaScript or slow network requests can exceed default timeouts. Increase the timeout:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.Timeout = 120; // 120 seconds

var pdf = renderer.RenderUrlAsPdf("https://slow-loading-site.com");
pdf.SaveAs("slow-content.pdf");
Enter fullscreen mode Exit fullscreen mode

If rendering exceeds the timeout, IronPDF throws an exception. I set timeouts based on expected page load times: 30s for internal pages, 60-120s for external URLs.

What's the Difference Between RenderDelay and Timeout?

  • Timeout: Maximum time allowed for the entire rendering process (loading HTML, executing JS, generating PDF)
  • RenderDelay: Wait time after page load before rendering begins (for JavaScript to complete)

Use both when dealing with slow Ajax or animations:

renderer.RenderingOptions.Timeout = 60; // Max 60 seconds total
renderer.RenderingOptions.RenderDelay = 2000; // Wait 2 seconds after load
Enter fullscreen mode Exit fullscreen mode

How Do I Debug Rendering Issues?

Enable JavaScript console logging to see errors:

using IronPdf;

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

renderer.RenderingOptions.JavascriptMessageListener = message =>
{
    Console.WriteLine($"JS: {message}");
};

var pdf = renderer.RenderHtmlAsPdf("<script>console.log('Test');</script>");
Enter fullscreen mode Exit fullscreen mode

This captures console.log, console.error, and other JavaScript output, helping diagnose why content isn't rendering as expected.

Can I Reuse Rendering Options Across Multiple PDFs?

Yes, create a renderer instance and reuse it:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

var pdf1 = renderer.RenderHtmlAsPdf("<h1>Document 1</h1>");
var pdf2 = renderer.RenderHtmlAsPdf("<h1>Document 2</h1>");

pdf1.SaveAs("doc1.pdf");
pdf2.SaveAs("doc2.pdf");
Enter fullscreen mode Exit fullscreen mode

This ensures consistent formatting across all generated PDFs and avoids reconfiguring options for each render.


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)