DEV Community

IronSoftware
IronSoftware

Posted on

HtmlRenderer.PdfSharp CSS Not Working (Issue Fixed)

When HtmlRenderer.PdfSharp CSS is not working, the cause is almost always the library's strict adherence to CSS 2.1 specification from 2011. This 15-year-old standard predates every modern CSS feature developers rely on today. Flexbox, Grid, CSS Variables, transforms, transitions, and even basic selectors like :nth-child and :not are completely unsupported.

This article documents exactly which CSS features fail in HtmlRenderer.PdfSharp, why they fail, and what developers can do when their HTML templates produce broken layouts.

The Problem

HtmlRenderer.PdfSharp is a third-party library that attempts to render HTML content using PdfSharp's PDF generation capabilities. The library explicitly targets HTML 4.01 and CSS Level 2 specifications. CSS Level 2.1 was finalized in 2011, a standard now over fifteen years old.

The practical impact: any CSS written using techniques from the last decade and a half will not render correctly. Developers attempting to convert modern web templates, Bootstrap layouts, Tailwind designs, or any HTML using contemporary CSS encounter output that looks nothing like their browser preview.

Symptoms Developers Experience

When HtmlRenderer.PdfSharp encounters unsupported CSS:

  • Flexbox layouts collapse: Elements styled with display: flex render as display: block, causing items to stack vertically instead of horizontally
  • Grid layouts fail completely: display: grid is ignored entirely, resulting in single-column output
  • CSS Variables are unresolved: Properties using var(--custom-property) receive no styling
  • Transforms are ignored: Rotated watermarks appear at 0 degrees, scaled elements retain original size
  • Modern selectors match nothing: :nth-child, :not, :first-of-type have no effect
  • Pseudo-elements disappear: ::before and ::after content is not generated
  • SVG graphics vanish: Inline SVG elements do not render

No error messages are produced. The failures are completely silent. Developers only discover the problems when viewing the generated PDF.

What CSS 2.1 Support Actually Means

CSS 2.1 includes only:

  • Basic selectors: element, class, ID
  • Font properties: font-family, font-size, font-weight, font-style
  • Text properties: color, text-align, text-decoration, line-height
  • Box model: margin, padding, border, width, height
  • Positioning: position (limited), top, left, right, bottom
  • Floats: float, clear
  • Basic display: block, inline, none, table
  • Background: background-color, background-image

CSS 2.1 does not include:

  • Flexbox (display: flex)
  • Grid (display: grid)
  • CSS Variables (--custom-property, var())
  • CSS Transforms (transform, rotate, scale, translate)
  • CSS Transitions (transition)
  • CSS Animations (@keyframes, animation)
  • Modern pseudo-selectors (:nth-child, :not, :has, :first-of-type)
  • Pseudo-elements (::before, ::after)
  • calc() function
  • box-sizing: border-box
  • Media queries (limited support)
  • @font-face web fonts (requires manual embedding)
  • SVG rendering

Who Is Affected

Developers using HtmlRenderer.PdfSharp encounter CSS issues across all development scenarios:

Frameworks and Environments:

  • .NET Framework 4.x applications
  • .NET Core and .NET 5+ projects (using community forks)
  • ASP.NET MVC and ASP.NET Core web applications
  • Console applications generating reports
  • Windows Services performing batch PDF generation

Use Cases:

  • Invoice and receipt generation with modern layouts
  • Report generation from HTML templates
  • Document conversion from web content
  • Email-to-PDF archival systems
  • Any project using Bootstrap, Tailwind, or modern CSS frameworks

Template Sources:

  • Bootstrap 4 or 5 templates (Flexbox-based grid system)
  • Tailwind CSS designs (utility-first, uses Flexbox and Grid extensively)
  • Material Design templates
  • Any HTML/CSS from 2012 or later

CSS Features That Do Not Work

The following sections document specific CSS features that HtmlRenderer.PdfSharp cannot process. Each represents a standard feature in modern web development that will fail silently.

Flexbox (display: flex) - Not Supported

CSS Flexbox is the foundation of modern web layout. HtmlRenderer.PdfSharp ignores all Flexbox properties.

/* None of these properties work */
.container {
    display: flex;           /* Treated as display: block */
    flex-direction: row;     /* Ignored */
    flex-wrap: wrap;         /* Ignored */
    justify-content: space-between;  /* Ignored */
    align-items: center;     /* Ignored */
    gap: 20px;               /* Ignored */
}

.item {
    flex: 1;                 /* Ignored */
    flex-grow: 1;            /* Ignored */
    flex-shrink: 0;          /* Ignored */
    flex-basis: 200px;       /* Ignored */
    order: 2;                /* Ignored */
    align-self: flex-end;    /* Ignored */
}
Enter fullscreen mode Exit fullscreen mode

Expected behavior: Items arrange horizontally with equal spacing.
Actual behavior: Items stack vertically as block elements.

A typical header layout:

<header style="display: flex; justify-content: space-between; align-items: center;">
    <div class="logo">Company Name</div>
    <nav>Navigation Items</nav>
</header>
Enter fullscreen mode Exit fullscreen mode

This renders as two stacked blocks, not a side-by-side layout.

CSS Grid (display: grid) - Not Supported

CSS Grid provides two-dimensional layout control. HtmlRenderer.PdfSharp has zero Grid support.

/* Grid is completely unsupported */
.dashboard {
    display: grid;                           /* Treated as display: block */
    grid-template-columns: repeat(3, 1fr);   /* Ignored */
    grid-template-rows: auto 1fr auto;       /* Ignored */
    grid-gap: 20px;                          /* Ignored */
    gap: 20px;                               /* Ignored */
    grid-template-areas:
        "header header header"
        "sidebar main main"
        "footer footer footer";              /* Ignored */
}

.sidebar {
    grid-area: sidebar;      /* Ignored */
    grid-column: 1;          /* Ignored */
    grid-row: 1 / 3;         /* Ignored */
}
Enter fullscreen mode Exit fullscreen mode

Expected behavior: A three-column dashboard layout.
Actual behavior: All items stack vertically in source order.

CSS Transforms - Not Supported

Transforms enable rotation, scaling, translation, and skewing. None work in HtmlRenderer.PdfSharp.

/* Transform properties are ignored */
.watermark {
    transform: rotate(-45deg);    /* Ignored - text appears horizontal */
    transform-origin: center;     /* Ignored */
}

.scaled-element {
    transform: scale(1.5);        /* Ignored - appears at 1x size */
}

.positioned-element {
    transform: translate(50px, 100px);  /* Ignored */
}

.combined-transform {
    transform: rotate(15deg) scale(1.2) translateX(20px);  /* All ignored */
}
Enter fullscreen mode Exit fullscreen mode

Watermarks intended to appear diagonally across pages will render as horizontal text in the top-left corner.

CSS Transitions and Animations - Not Supported

Transitions and animations have no effect (though this matters less for static PDF output).

/* Transitions and animations are ignored */
.button {
    transition: background-color 0.3s ease;  /* Ignored */
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.animated {
    animation: fadeIn 1s ease;    /* Ignored */
}
Enter fullscreen mode Exit fullscreen mode

CSS Variables (Custom Properties) - Not Supported

CSS Variables provide theming and reusable values. HtmlRenderer.PdfSharp cannot process them.

/* CSS Variables are not interpreted */
:root {
    --primary-color: #3498db;
    --secondary-color: #2c3e50;
    --spacing: 16px;
    --border-radius: 4px;
}

.button {
    background-color: var(--primary-color);   /* Receives no color */
    padding: var(--spacing);                   /* Receives no padding */
    border-radius: var(--border-radius);       /* Receives no radius */
    color: var(--secondary-color);             /* Receives no color */
}
Enter fullscreen mode Exit fullscreen mode

Expected behavior: Button with custom colors and spacing.
Actual behavior: Unstyled button, likely with black text and no background.

calc() Function - Not Supported

The calc() function enables mathematical calculations in CSS values.

/* calc() expressions are not evaluated */
.sidebar {
    width: calc(100% - 250px);           /* Likely ignored entirely */
}

.content {
    padding: calc(10px + 2%);            /* Likely ignored */
    margin-top: calc(var(--spacing) * 2);  /* Definitely ignored */
}

.responsive-element {
    width: calc(50vw - 20px);            /* Ignored */
}
Enter fullscreen mode Exit fullscreen mode

Properties using calc() may be ignored entirely or cause layout errors.

Modern Pseudo-Selectors - Not Supported

Selectors introduced in CSS3 do not work.

/* These selectors are not recognized */

/* :nth-child variations */
tr:nth-child(odd) { background: #f2f2f2; }   /* No alternating rows */
tr:nth-child(even) { background: white; }
tr:nth-child(3n+1) { border-left: 3px solid blue; }
li:nth-child(-n+3) { font-weight: bold; }    /* First 3 items not bolded */

/* Negation pseudo-class */
.item:not(.active) { opacity: 0.5; }         /* All items full opacity */
input:not([type="submit"]) { border: 1px solid gray; }

/* Structural pseudo-classes */
p:first-of-type { margin-top: 0; }
div:last-of-type { margin-bottom: 0; }
:only-child { margin: 0 auto; }

/* :has() relational pseudo-class */
.parent:has(.child) { border: 1px solid blue; }  /* Not supported */
Enter fullscreen mode Exit fullscreen mode

Alternating table row colors, negation selectors, and structural selectors all fail. Developers must add explicit classes to each element.

Pseudo-Elements (::before, ::after) - Not Supported

Generated content using pseudo-elements does not render.

/* Pseudo-element content is not generated */
.quote::before {
    content: open-quote;         /* Does not appear */
}

.quote::after {
    content: close-quote;        /* Does not appear */
}

.required-field::after {
    content: ' *';               /* Does not appear */
    color: red;
}

.clearfix::after {
    content: '';
    display: table;
    clear: both;                 /* Clearfix pattern fails */
}

.icon::before {
    content: '\f007';            /* Font Awesome icons don't render */
    font-family: 'Font Awesome';
}
Enter fullscreen mode Exit fullscreen mode

Required field indicators, decorative content, and icon fonts using pseudo-elements will not appear.

JavaScript - Not Supported

HtmlRenderer.PdfSharp has no JavaScript engine.

<!-- JavaScript is never executed -->
<script>
    // This code never runs
    document.getElementById('date').innerText = new Date().toLocaleDateString();

    // Dynamic content generation fails
    fetch('/api/data').then(r => r.json()).then(data => {
        document.getElementById('content').innerHTML = data.html;
    });

    // Client-side rendering frameworks produce blank output
    // React, Vue, Angular components won't render
</script>
Enter fullscreen mode Exit fullscreen mode

Any content that depends on JavaScript for rendering will not appear. This includes:

  • React, Vue, Angular single-page applications
  • Dynamic content loading
  • Client-side templating
  • Date/time formatting via JavaScript
  • Charting libraries (Chart.js, D3.js)

SVG Rendering - Not Supported

Scalable Vector Graphics support is absent or severely limited.

<!-- SVG elements may not render at all -->
<svg width="100" height="100">
    <circle cx="50" cy="50" r="40" fill="#3498db"/>
    <rect x="10" y="10" width="30" height="30" fill="#2ecc71"/>
    <text x="50" y="55" text-anchor="middle">SVG</text>
    <path d="M10 80 Q 52.5 10, 95 80 T 180 80" fill="none" stroke="black"/>
</svg>

<img src="logo.svg" alt="Logo">  <!-- SVG via img tag may also fail -->
Enter fullscreen mode Exit fullscreen mode

SVG icons, charts, logos, and graphics will not appear in the PDF output.

Web Fonts (@font-face) - Manual Embedding Required

Custom fonts do not load automatically.

/* @font-face declarations are not automatically processed */
@font-face {
    font-family: 'CustomFont';
    src: url('fonts/custom-font.woff2') format('woff2'),
         url('fonts/custom-font.woff') format('woff');
}

body {
    font-family: 'CustomFont', Arial, sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

Google Fonts, Adobe Fonts, and self-hosted web fonts will not load. Text using undefined fonts falls back to a default system font, causing visual inconsistency with the browser preview.

Bootstrap and Tailwind Compatibility Issues

Modern CSS frameworks depend on features that HtmlRenderer.PdfSharp cannot process.

Bootstrap 5 Layouts Break

Bootstrap 5 uses Flexbox for its grid system and utility classes.

<!-- Bootstrap 5 grid system will not work -->
<div class="container">
    <div class="row">
        <div class="col-md-4">Column 1</div>
        <div class="col-md-4">Column 2</div>
        <div class="col-md-4">Column 3</div>
    </div>
</div>

<!-- Flexbox utilities fail -->
<div class="d-flex justify-content-between align-items-center">
    <span>Left aligned</span>
    <span>Right aligned</span>
</div>

<!-- Card layouts using Flexbox collapse -->
<div class="card-group">
    <div class="card">Card 1</div>
    <div class="card">Card 2</div>
    <div class="card">Card 3</div>
</div>
Enter fullscreen mode Exit fullscreen mode

Bootstrap's row and col-* classes use display: flex. The columns will stack vertically instead of appearing side by side. Utility classes like d-flex, justify-content-*, align-items-*, and spacing utilities like gap-* are all Flexbox-based and fail.

Tailwind CSS Fails Extensively

Tailwind's utility-first approach relies heavily on unsupported CSS features.

<!-- Tailwind utilities that will not work -->
<div class="flex items-center justify-between gap-4 p-4">
    <div class="flex-1">Flexible item</div>
    <div class="w-1/3">Fixed width</div>
</div>

<div class="grid grid-cols-3 gap-4">
    <div>Grid item 1</div>
    <div>Grid item 2</div>
    <div>Grid item 3</div>
</div>

<div class="transform rotate-45 scale-150">
    Transformed element
</div>

<div class="bg-[var(--custom-color)]">
    CSS variable usage
</div>
Enter fullscreen mode Exit fullscreen mode

Flexbox utilities (flex, items-*, justify-*), Grid utilities (grid, grid-cols-*, gap-*), transform utilities (transform, rotate-*, scale-*), and arbitrary value syntax with CSS variables all fail.

Resulting Output

When Bootstrap or Tailwind HTML is processed by HtmlRenderer.PdfSharp:

  • Multi-column layouts collapse to a single column
  • Centered content aligns to the left
  • Flexible widths become 100% width or undefined
  • Grid items stack vertically
  • Spacing between items disappears
  • Transformed elements appear untransformed
  • Custom colors and spacing from variables are lost

The PDF output does not resemble the browser preview.

Evidence from the Developer Community

Developers have documented HtmlRenderer.PdfSharp's CSS limitations across multiple platforms.

Stack Overflow Reports

Stack Overflow contains numerous questions about HtmlRenderer.PdfSharp CSS not working:

"I'm trying to convert HTML to PDF using HtmlRenderer.PdfSharp but my flexbox layouts are completely broken. The elements just stack on top of each other."
— Stack Overflow, 2023

"PDFsharp with HtmlRenderer doesn't support CSS grid at all. I had to rewrite my entire template using tables."
— Stack Overflow, 2022

"Is there any way to get nth-child selectors working in HtmlRenderer.PdfSharp? My alternating row colors aren't showing."
— Stack Overflow, 2021

GitHub Issues

The HtmlRenderer repository contains issues documenting these limitations:

"CSS letter-spacing property doesn't work. I've tried multiple approaches but the text always renders without spacing adjustments."
GitHub Issue{:rel="nofollow"}

"Table headers with display: table-header-group don't repeat on subsequent pages as they should according to CSS spec."
GitHub Issue #193{:rel="nofollow"}

"External CSS files don't load reliably. I have to inline all my styles."
GitHub Issue #65{:rel="nofollow"}

PdfSharp Forum Discussions

The official PdfSharp forum contains threads about CSS limitations:

"I've been struggling with float layouts. Even basic float: left doesn't work consistently."
PdfSharp Forum{:rel="nofollow"}

"Bootstrap columns don't render correctly at all. Had to switch to table-based layouts."
— PdfSharp Forum, 2022

Root Cause Analysis

The CSS limitations in HtmlRenderer.PdfSharp are architectural, not implementation oversights.

Custom Parsing Engine

HtmlRenderer uses a custom-built HTML and CSS parsing engine. This engine was designed to support HTML 4.01 and CSS Level 2.1 specifications. Adding support for CSS3 features would require:

  1. Extending the CSS parser to recognize new properties and values
  2. Implementing the layout algorithms for Flexbox and Grid
  3. Adding a JavaScript engine for dynamic content
  4. Implementing SVG rendering
  5. Updating constantly as web standards evolve

This would essentially mean building a browser rendering engine, a project requiring years of development and ongoing maintenance.

Why No Updates

HtmlRenderer has not seen significant feature updates in years. The project remains focused on CSS 2.1 compatibility. There is no roadmap for CSS3 support because:

  1. CSS3 implementation would require a near-complete rewrite
  2. The scope would expand to match browser development complexity
  3. Existing browser engines already provide this functionality
  4. Maintaining CSS standard compliance is a massive ongoing effort

Design Limitation vs Bug

The CSS gaps in HtmlRenderer.PdfSharp are not bugs to be fixed. They represent the boundaries of what a custom rendering engine can reasonably achieve. The library does what it was designed to do: render CSS 2.1 content. Modern CSS support was never a design goal.

Attempted Workarounds

Developers have tried various approaches to work around HtmlRenderer.PdfSharp's limitations.

Workaround 1: Float-Based Layouts

Approach: Replace Flexbox and Grid with CSS floats.

/* Fallback to float layouts */
.container {
    overflow: hidden; /* clearfix */
}

.column {
    float: left;
    width: 33.333%;
    box-sizing: border-box;
    padding: 10px;
}

/* Clear float after container */
.container::after {
    content: '';
    display: table;
    clear: both;
}
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • ::after pseudo-element doesn't work for clearfix
  • Vertical centering is difficult
  • Equal-height columns require additional hacks
  • Cannot replicate many Flexbox behaviors
  • Responsive design becomes complex

Workaround 2: Table-Based Layouts

Approach: Use HTML tables or CSS display: table for column layouts.

<table style="width: 100%;">
    <tr>
        <td style="width: 33%;">Column 1</td>
        <td style="width: 33%;">Column 2</td>
        <td style="width: 33%;">Column 3</td>
    </tr>
</table>
Enter fullscreen mode Exit fullscreen mode

Or using CSS:

.table-container {
    display: table;
    width: 100%;
}

.table-row {
    display: table-row;
}

.table-cell {
    display: table-cell;
    vertical-align: middle;
    padding: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Semantic HTML concerns
  • Limited flexibility
  • Cannot reorder items
  • Nested layouts become unwieldy
  • Not suitable for complex designs

Workaround 3: Inline-Block Columns

Approach: Use display: inline-block with calculated widths.

.row {
    font-size: 0; /* Remove whitespace between inline-blocks */
}

.column {
    display: inline-block;
    width: 33.333%;
    font-size: 16px; /* Reset font size */
    vertical-align: top;
}
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Whitespace handling is fragile
  • Width calculations must be precise
  • Vertical alignment options are limited
  • Cannot achieve spacing without margin calculations

Workaround 4: Inline Styles with Explicit Widths

Approach: Use inline styles with pixel values instead of CSS files.

<div style="width: 600px;">
    <div style="float: left; width: 200px; padding: 10px;">Column 1</div>
    <div style="float: left; width: 200px; padding: 10px;">Column 2</div>
    <div style="float: left; width: 200px; padding: 10px;">Column 3</div>
    <div style="clear: both;"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Limitations:

  • Maintenance nightmare
  • Cannot use variables or theming
  • Responsive design impossible
  • Violates separation of concerns

None of these workarounds provide the functionality of modern CSS. They offer partial solutions for simple layouts but fail for complex designs.

A Different Approach: IronPDF

For developers who require modern CSS support, IronPDF provides a fundamentally different architecture. Instead of a custom CSS parser limited to 2011 specifications, IronPDF embeds the Chromium rendering engine—the same engine that powers Google Chrome and Microsoft Edge.

Architectural Difference

Aspect HtmlRenderer.PdfSharp IronPDF
Rendering Engine Custom parser Chromium
CSS Specification CSS 2.1 (2011) Current web standards
Flexbox Not supported Full support
Grid Not supported Full support
CSS Variables Not supported Full support
Transforms Not supported Full support
JavaScript Not supported V8 engine
SVG Not supported Full support
Web Fonts Manual embedding Automatic loading

When HTML is submitted to IronPDF, Chromium processes it exactly as a browser would. The rendered output matches what developers see in Chrome.

Code Example: Modern CSS Layout

The following example demonstrates rendering HTML with CSS features that HtmlRenderer.PdfSharp cannot process.

using IronPdf;

// Demonstrates rendering modern CSS that fails in HtmlRenderer.PdfSharp
// IronPDF's Chromium engine processes all CSS3 features

public class ModernCssRenderer
{
    public void RenderModernCssTemplate()
    {
        // Create renderer using embedded Chromium engine
        var renderer = new ChromePdfRenderer();

        // HTML content using CSS3 features
        string html = @"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                /* CSS Variables - ignored by HtmlRenderer.PdfSharp */
                :root {
                    --primary-color: #2c3e50;
                    --accent-color: #3498db;
                    --spacing: 16px;
                    --border-radius: 8px;
                }

                body {
                    font-family: 'Segoe UI', Arial, sans-serif;
                    margin: 0;
                    padding: var(--spacing);
                    color: var(--primary-color);
                }

                /* Flexbox header - ignored by HtmlRenderer.PdfSharp */
                .header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: var(--spacing);
                    background: linear-gradient(to right, var(--primary-color), var(--accent-color));
                    color: white;
                    border-radius: var(--border-radius);
                    margin-bottom: calc(var(--spacing) * 2);
                }

                .logo {
                    font-size: 1.5em;
                    font-weight: bold;
                }

                /* CSS Grid layout - ignored by HtmlRenderer.PdfSharp */
                .stats-grid {
                    display: grid;
                    grid-template-columns: repeat(3, 1fr);
                    gap: var(--spacing);
                    margin-bottom: var(--spacing);
                }

                .stat-card {
                    background: white;
                    padding: var(--spacing);
                    border-radius: var(--border-radius);
                    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                    text-align: center;
                }

                .stat-value {
                    font-size: 2em;
                    color: var(--accent-color);
                    font-weight: bold;
                }

                /* :nth-child selectors - ignored by HtmlRenderer.PdfSharp */
                .data-table tr:nth-child(odd) {
                    background-color: #f8f9fa;
                }

                .data-table tr:nth-child(even) {
                    background-color: white;
                }

                .data-table {
                    width: 100%;
                    border-collapse: collapse;
                }

                .data-table th, .data-table td {
                    padding: 12px;
                    text-align: left;
                    border-bottom: 1px solid #ddd;
                }

                .data-table th {
                    background-color: var(--primary-color);
                    color: white;
                }

                /* Pseudo-elements - ignored by HtmlRenderer.PdfSharp */
                .required::after {
                    content: ' *';
                    color: #e74c3c;
                }

                /* Transform for watermark - ignored by HtmlRenderer.PdfSharp */
                .watermark {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%) rotate(-45deg);
                    font-size: 72px;
                    color: rgba(0,0,0,0.05);
                    pointer-events: none;
                    z-index: -1;
                }
            </style>
        </head>
        <body>
            <div class='watermark'>CONFIDENTIAL</div>

            <div class='header'>
                <div class='logo'>Acme Corporation</div>
                <div>Q4 2025 Report</div>
            </div>

            <div class='stats-grid'>
                <div class='stat-card'>
                    <div class='stat-value'>$1.2M</div>
                    <div>Revenue</div>
                </div>
                <div class='stat-card'>
                    <div class='stat-value'>847</div>
                    <div>Customers</div>
                </div>
                <div class='stat-card'>
                    <div class='stat-value'>94%</div>
                    <div>Satisfaction</div>
                </div>
            </div>

            <h2>Sales Data</h2>
            <table class='data-table'>
                <thead>
                    <tr>
                        <th><span class='required'>Product</span></th>
                        <th>Units Sold</th>
                        <th>Revenue</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>Widget Pro</td>
                        <td>1,234</td>
                        <td>$246,800</td>
                    </tr>
                    <tr>
                        <td>Widget Standard</td>
                        <td>2,567</td>
                        <td>$384,050</td>
                    </tr>
                    <tr>
                        <td>Widget Basic</td>
                        <td>3,891</td>
                        <td>$311,280</td>
                    </tr>
                    <tr>
                        <td>Services</td>
                        <td>156</td>
                        <td>$312,000</td>
                    </tr>
                </tbody>
            </table>
        </body>
        </html>";

        // Render to PDF using Chromium - all CSS features work
        var pdf = renderer.RenderHtmlAsPdf(html);

        pdf.SaveAs("modern-report.pdf");
    }
}
Enter fullscreen mode Exit fullscreen mode

What renders correctly with IronPDF that fails in HtmlRenderer.PdfSharp:

  • CSS Variables (--primary-color, var()) - colors and spacing applied
  • Flexbox header - logo and date on opposite sides
  • CSS Grid - three stat cards in a row
  • :nth-child - alternating table row colors
  • ::after pseudo-element - required field indicator appears
  • Transform - diagonal watermark positioned correctly
  • calc() function - spacing calculations work
  • Linear gradients - header background gradient renders

Converting a Bootstrap 5 Template

IronPDF renders Bootstrap 5 layouts correctly:

using IronPdf;

public class BootstrapPdfGenerator
{
    public void GenerateBootstrapReport()
    {
        var renderer = new ChromePdfRenderer();

        string html = @"
        <!DOCTYPE html>
        <html>
        <head>
            <link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>
        </head>
        <body class='p-4'>
            <div class='container'>
                <div class='row mb-4'>
                    <div class='col-6'>
                        <h1>Invoice #12345</h1>
                    </div>
                    <div class='col-6 text-end'>
                        <p class='lead'>Due: February 28, 2026</p>
                    </div>
                </div>

                <div class='row'>
                    <div class='col-4'>
                        <div class='card'>
                            <div class='card-body'>
                                <h5 class='card-title'>Subtotal</h5>
                                <p class='card-text fs-3'>$1,500.00</p>
                            </div>
                        </div>
                    </div>
                    <div class='col-4'>
                        <div class='card'>
                            <div class='card-body'>
                                <h5 class='card-title'>Tax (10%)</h5>
                                <p class='card-text fs-3'>$150.00</p>
                            </div>
                        </div>
                    </div>
                    <div class='col-4'>
                        <div class='card bg-primary text-white'>
                            <div class='card-body'>
                                <h5 class='card-title'>Total</h5>
                                <p class='card-text fs-3'>$1,650.00</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </body>
        </html>";

        // Bootstrap's Flexbox grid renders correctly
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("bootstrap-invoice.pdf");
    }
}
Enter fullscreen mode Exit fullscreen mode

Bootstrap's row and col-* classes work as expected. Cards display in three columns. Text alignment utilities function correctly.

API Reference

For detailed documentation on IronPDF rendering:

Migration Considerations

Licensing

HtmlRenderer.PdfSharp and PdfSharp are open source (MIT License). IronPDF is commercial software with per-developer licensing. A free trial is available for evaluation, and a free tier exists for development purposes.

For projects that require modern CSS support, the licensing cost is typically offset by reduced development time. The hours spent maintaining CSS 2.1 fallback stylesheets often exceed the license cost.

API Migration

Migration from HtmlRenderer.PdfSharp to IronPDF is straightforward because both accept HTML strings:

HtmlRenderer.PdfSharp:

using PdfSharp.Pdf;
using TheArtOfDev.HtmlRenderer.PdfSharp;

PdfDocument pdf = PdfGenerator.GeneratePdf(htmlContent, PdfSharp.PageSize.A4);
pdf.Save("output.pdf");
Enter fullscreen mode Exit fullscreen mode

IronPDF:

using IronPdf;

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

What You Gain

  • Full CSS3 support including Flexbox and Grid
  • CSS Variables and calc() functions
  • CSS Transforms for watermarks and rotated content
  • Modern pseudo-selectors (:nth-child, :not, etc.)
  • Pseudo-elements (::before, ::after)
  • JavaScript execution for dynamic content
  • SVG rendering
  • Automatic web font loading
  • URL-to-PDF conversion capability
  • Active development and regular updates

What to Consider

  • Commercial licensing required for production deployment
  • Larger package size due to embedded Chromium
  • Higher memory consumption during rendering
  • Initial learning curve for advanced configuration options

Conclusion

When HtmlRenderer.PdfSharp CSS is not working, the underlying cause is the library's CSS 2.1 limitation. This 15-year-old specification predates Flexbox, Grid, CSS Variables, transforms, modern selectors, pseudo-elements, and virtually every CSS feature used in contemporary web development.

No configuration change or workaround can add these features to HtmlRenderer.PdfSharp. The library renders CSS 2.1 content as designed. Developers requiring modern CSS support need a rendering engine based on current web standards.

IronPDF provides this through its embedded Chromium engine. HTML and CSS that render correctly in Chrome produce identical output in IronPDF, eliminating the need for legacy CSS workarounds and separate PDF-specific stylesheets.


Written by Jacob Mellor, CTO at Iron Software with 25+ years of experience in developer tooling.


References

  1. HtmlRenderer.PdfSharp NuGet Package{:rel="nofollow"} - Package description confirming HTML 4.01 and CSS Level 2 support
  2. CSS 2.1 Specification{:rel="nofollow"} - W3C CSS Level 2 Revision 1 specification from 2011
  3. CSS Flexible Box Layout Module{:rel="nofollow"} - W3C Flexbox specification (not supported by HtmlRenderer)
  4. CSS Grid Layout Module{:rel="nofollow"} - W3C Grid specification (not supported by HtmlRenderer)
  5. ArthurHub/HTML-Renderer GitHub Repository{:rel="nofollow"} - Source repository for HtmlRenderer library
  6. GitHub Issue #193 - Table Header Repetition{:rel="nofollow"} - Bug report on CSS table features
  7. GitHub Issue #65 - External CSS Loading{:rel="nofollow"} - Discussion on stylesheet loading issues
  8. PdfSharp Forum - CSS Support Discussions{:rel="nofollow"} - Forum threads on CSS limitations

For comprehensive IronPDF documentation including tutorials, API reference, and code examples, visit ironpdf.com.

Top comments (0)