Developers using iText 7's pdfHTML add-on discover that CSS Flexbox layouts do not render correctly. Elements positioned with display: flex collapse or misalign, breaking modern responsive designs. This limitation affects developers who design HTML templates with current CSS practices. This article documents the CSS support gaps and examines alternatives with complete CSS3 support.
The Problem
iText's pdfHTML add-on converts HTML and CSS to PDF, but its CSS engine does not fully implement CSS3 specifications. Flexbox, CSS Grid, and other modern layout features either do not work or produce incorrect output.
When HTML containing Flexbox is processed:
-
display: flexmay be ignored entirely -
justify-contentandalign-itemshave no effect - Flex items stack vertically instead of horizontally
-
flex-wrapdoes not wrap items correctly
Error Messages and Symptoms
There are typically no errors - the layout simply renders incorrectly:
/* This layout works in browsers but breaks in pdfHTML */
.container {
display: flex;
justify-content: space-between;
align-items: center;
}
Output shows:
- Items stacked vertically instead of side-by-side
- No spacing between elements
- Alignment properties ignored
Developers often discover this only after building complete HTML templates.
Who Is Affected
This issue impacts developers using modern CSS:
Use Cases: Invoice generation, report templates, document automation, any PDF generation using HTML designed for web.
CSS Features Not Supported:
-
display: flexand Flexbox properties -
display: gridand CSS Grid - CSS custom properties (variables)
- Modern pseudo-selectors
Evidence from the Developer Community
From iText documentation and community reports:
"pdfHTML supports a subset of CSS. Some CSS3 properties are not implemented."
— iText Documentation"My template works in the browser but the layout is completely wrong in the generated PDF."
— Developer report, 2023
Comprehensive CSS Support Matrix
The following matrix documents CSS feature support in iText pdfHTML based on official documentation and developer reports:
Layout Features
| CSS Feature | pdfHTML Support | Notes |
|---|---|---|
display: flex |
Not supported | Elements render as block |
display: grid |
Not supported | Elements render as block |
display: inline-flex |
Not supported | Elements render as inline |
flex-direction |
Not supported | - |
flex-wrap |
Not supported | - |
justify-content |
Not supported | - |
align-items |
Not supported | - |
align-self |
Not supported | - |
flex-grow/shrink |
Not supported | - |
grid-template-columns |
Not supported | - |
grid-gap / gap
|
Not supported | - |
position: sticky |
Not supported | Falls back to relative |
position: fixed |
Limited | May not work as expected |
CSS3 Features
| CSS Feature | pdfHTML Support | Notes |
|---|---|---|
CSS Variables (--custom) |
Not supported | Variables not resolved |
calc() |
Limited | Simple expressions only |
@media queries |
Limited | Print media partially supported |
@font-face |
Limited | Requires specific configuration |
@keyframes / animations |
Not supported | Static output only |
transform |
Limited | Basic transforms only |
transition |
Not supported | - |
filter |
Not supported | - |
backdrop-filter |
Not supported | - |
clip-path |
Not supported | - |
Box Model and Sizing
| CSS Feature | pdfHTML Support | Notes |
|---|---|---|
box-sizing |
Supported | - |
min-width/height |
Supported | - |
max-width/height |
Supported | - |
margin |
Supported | - |
padding |
Supported | - |
border |
Supported | - |
border-radius |
Limited | May not render correctly |
box-shadow |
Limited | Basic shadows only |
Pseudo-elements and Selectors
| CSS Feature | pdfHTML Support | Notes |
|---|---|---|
::before / ::after
|
Limited | Basic support |
:nth-child() |
Supported | - |
:hover / :focus
|
Not applicable | No interactivity |
::placeholder |
Not supported | - |
:has() |
Not supported | - |
:where() / :is()
|
Not supported | - |
Root Cause Analysis
pdfHTML uses a custom CSS engine built specifically for PDF generation, not a browser rendering engine. This architectural choice has significant implications for CSS support.
Why Flexbox and Grid Are Missing
Implementing CSS Flexbox and Grid requires:
- Complete CSS specification parsing: The Flexbox specification alone is over 100 pages of layout algorithms
- Layout algorithm implementation: Each layout mode (flex, grid, table, block, inline) requires separate implementation
- Box model calculations: Nested layouts with different display modes must interact correctly
- Intrinsic sizing: Flex and grid items have complex minimum/maximum size calculations
- Alignment algorithms: justify-content, align-items, and related properties require precise positioning
Implementing these features to browser-specification compliance would essentially mean building a browser rendering engine. iText's core product focus is PDF manipulation (creation, editing, form filling, extraction), not web rendering.
The pdfHTML Scope
pdfHTML is positioned as a commercial add-on that converts "simple HTML and CSS" to PDF. From iText's perspective:
- Documents with basic formatting (headings, paragraphs, tables, lists)
- Inline styles and simple external stylesheets
- Basic positioning with floats and absolute positioning
- Print-oriented layouts designed for PDF output
This scope explicitly excludes:
- Modern web layouts designed for browsers
- Single-page application (SPA) rendering
- JavaScript-generated content
- Responsive designs that adapt to viewport
Why This Matters for Developers
Modern web development has shifted to Flexbox and Grid as primary layout mechanisms:
/* Common modern patterns that don't work in pdfHTML */
/* Navigation bar */
.navbar {
display: flex;
justify-content: space-between;
}
/* Card grid */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
/* Centered content */
.center {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
Developers who build templates for web viewing expect these patterns to work in PDF output.
Attempted Workarounds
Workaround 1: Use Tables Instead of Flexbox
Approach: Replace Flexbox layouts with HTML tables.
<!-- Instead of Flexbox -->
<div style="display: flex; justify-content: space-between;">
<div>Left</div>
<div>Right</div>
</div>
<!-- Use tables -->
<table style="width: 100%;">
<tr>
<td style="text-align: left;">Left</td>
<td style="text-align: right;">Right</td>
</tr>
</table>
Limitations:
- Requires rewriting templates
- Tables have semantic issues
- Complex nested layouts become unwieldy
- Not a one-to-one replacement for Flexbox capabilities
Workaround 2: Maintain Separate PDF Templates
Approach: Create simplified templates specifically for PDF generation.
Limitations:
- Doubles template maintenance effort
- Visual inconsistency between web and PDF
- Changes must be made in two places
Workaround 3: Use Inline Styles and Absolute Positioning
Approach: Use explicit widths and absolute positioning.
<div style="position: relative; height: 50px;">
<div style="position: absolute; left: 0;">Left</div>
<div style="position: absolute; right: 0;">Right</div>
</div>
Limitations:
- Fragile and hard to maintain
- Does not scale to complex layouts
- Manual pixel calculations required
A Different Approach: IronPDF
IronPDF uses Chromium for rendering, providing complete CSS3 support including Flexbox and Grid.
Why IronPDF Supports Modern CSS
IronPDF embeds the same Chromium engine used in Google Chrome. This means:
- Complete CSS3: Every CSS feature Chrome supports, IronPDF supports
- Flexbox and Grid: Modern layouts work exactly as in the browser
- CSS Variables: Custom properties work correctly
- Media Queries: Print-specific styles are respected
Code Example
using IronPdf;
public class ModernLayoutGenerator
{
public byte[] GenerateFlexboxDocument()
{
var renderer = new ChromePdfRenderer();
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--primary-color: #2563eb;
--spacing: 20px;
}
body {
font-family: 'Segoe UI', Arial, sans-serif;
margin: 0;
padding: var(--spacing);
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing);
background: var(--primary-color);
color: white;
}
.card-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing);
margin-top: var(--spacing);
}
.card {
display: flex;
flex-direction: column;
padding: var(--spacing);
border: 1px solid #ddd;
border-radius: 8px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-bottom: 10px;
}
.card-value {
font-size: 2rem;
font-weight: bold;
color: var(--primary-color);
}
.footer {
display: flex;
justify-content: center;
gap: var(--spacing);
margin-top: var(--spacing);
padding-top: var(--spacing);
border-top: 1px solid #ddd;
}
@media print {
.card-container {
grid-template-columns: repeat(2, 1fr);
}
}
</style>
</head>
<body>
<div class='header'>
<h1>Dashboard Report</h1>
<span>Q4 2025</span>
</div>
<div class='card-container'>
<div class='card'>
<div class='card-header'>
<span>Revenue</span>
<span>+12%</span>
</div>
<div class='card-value'>$2.4M</div>
</div>
<div class='card'>
<div class='card-header'>
<span>Users</span>
<span>+8%</span>
</div>
<div class='card-value'>48.2K</div>
</div>
<div class='card'>
<div class='card-header'>
<span>Orders</span>
<span>+15%</span>
</div>
<div class='card-value'>12.8K</div>
</div>
</div>
<div class='footer'>
<span>Generated: " + DateTime.Now.ToString("yyyy-MM-dd") + @"</span>
</div>
</body>
</html>";
using var pdf = renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
}
Key points:
- CSS Variables work (
--primary-color,--spacing) - Flexbox layouts render correctly
- CSS Grid creates responsive columns
-
@media printquery is respected
Code Example: CSS Grid Layout
public byte[] GenerateGridReport()
{
var renderer = new ChromePdfRenderer();
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: 'Segoe UI', sans-serif;
margin: 0;
padding: 20px;
}
.report-grid {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: auto 1fr auto;
gap: 20px;
min-height: 100vh;
}
.header {
grid-column: 1 / -1;
background: linear-gradient(135deg, #1e3c72, #2a5298);
color: white;
padding: 30px;
border-radius: 8px;
}
.sidebar {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
}
.main-content {
background: white;
padding: 20px;
border: 1px solid #e9ecef;
border-radius: 8px;
}
.footer {
grid-column: 1 / -1;
text-align: center;
padding: 15px;
background: #343a40;
color: white;
border-radius: 8px;
}
.stat-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.stat-card {
padding: 15px;
background: white;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div class='report-grid'>
<div class='header'>
<h1>Annual Report 2025</h1>
<p>Financial Overview and Performance Metrics</p>
</div>
<div class='sidebar'>
<h3>Quick Stats</h3>
<div class='stat-grid'>
<div class='stat-card'>
<div>Revenue</div>
<strong>$12.4M</strong>
</div>
<div class='stat-card'>
<div>Growth</div>
<strong>+23%</strong>
</div>
<div class='stat-card'>
<div>Customers</div>
<strong>8,432</strong>
</div>
<div class='stat-card'>
<div>NPS Score</div>
<strong>72</strong>
</div>
</div>
</div>
<div class='main-content'>
<h2>Executive Summary</h2>
<p>This year demonstrated strong performance across all key metrics...</p>
</div>
<div class='footer'>
<p>Generated: " + DateTime.Now.ToString("MMMM dd, yyyy") + @"</p>
</div>
</div>
</body>
</html>";
using var pdf = renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
Code Example: Flexbox Navigation and Card Layout
public byte[] GenerateFlexboxDocument()
{
var renderer = new ChromePdfRenderer();
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px;
background: #2c3e50;
color: white;
}
.nav-links {
display: flex;
gap: 25px;
list-style: none;
}
.content {
padding: 30px;
}
.card-row {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.card {
flex: 1;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
display: flex;
flex-direction: column;
}
.card-title {
font-weight: bold;
margin-bottom: 10px;
}
.card-content {
flex: 1;
}
.card-footer {
margin-top: auto;
padding-top: 15px;
border-top: 1px solid #dee2e6;
}
</style>
</head>
<body>
<nav class='navbar'>
<div class='logo'>Company Name</div>
<ul class='nav-links'>
<li>Dashboard</li>
<li>Reports</li>
<li>Settings</li>
</ul>
</nav>
<div class='content'>
<div class='card-row'>
<div class='card'>
<div class='card-title'>Sales</div>
<div class='card-content'>Monthly sales figures and trends.</div>
<div class='card-footer'>Updated: Today</div>
</div>
<div class='card'>
<div class='card-title'>Inventory</div>
<div class='card-content'>Current stock levels and alerts.</div>
<div class='card-footer'>Updated: Today</div>
</div>
<div class='card'>
<div class='card-title'>Orders</div>
<div class='card-content'>Pending and completed orders.</div>
<div class='card-footer'>Updated: Today</div>
</div>
</div>
</div>
</body>
</html>";
using var pdf = renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
API Reference
For CSS support details:
Migration Considerations
Licensing
- iText pdfHTML is a commercial add-on
- IronPDF is commercial software with perpetual licensing
- IronPDF Licensing
API Differences
- iText:
HtmlConverter.ConvertToPdf() - IronPDF:
ChromePdfRenderer.RenderHtmlAsPdf() - HTML templates typically work unchanged with IronPDF
What You Gain
- Complete CSS3 support (Flexbox, Grid, Variables)
- Same templates work for web and PDF
- No need for fallback layouts
What to Consider
- Different library, different API
- Chromium-based rendering
- Commercial licensing for both options
Conclusion
iText pdfHTML's limited CSS support forces developers to choose between modern web layouts and PDF generation. Maintaining separate templates doubles effort and introduces inconsistency. For projects where HTML templates need to render identically in browsers and PDFs, Chromium-based rendering provides the CSS compatibility that custom rendering engines cannot match.
Written by Jacob Mellor, who leads technical development at Iron Software.
References
- iText pdfHTML Documentation{:rel="nofollow"} - CSS limitations noted
For the latest IronPDF documentation and tutorials, visit ironpdf.com.
Top comments (0)