Developers using wkhtmltopdf for HTML-to-PDF conversion frequently encounter broken layouts, missing styles, and completely ignored CSS properties. The root cause: wkhtmltopdf relies on Qt WebKit, a rendering engine frozen in time around 2012. Modern CSS features like Flexbox and Grid simply do not exist in this engine, and they never will—the wkhtmltopdf project has been officially archived.
The Problem
wkhtmltopdf converts HTML to PDF using Qt WebKit, a browser engine that predates modern CSS layout systems. When developers attempt to render HTML documents that use contemporary CSS, they encounter three categories of failures:
Complete feature absence: CSS Flexbox and CSS Grid properties are entirely unsupported. The engine does not recognize
display: flex,display: grid, or any related properties.Partial CSS3 support: Many CSS3 properties either fail silently or render incorrectly. This includes transforms, animations, custom properties (CSS variables), and advanced selectors.
Inconsistent rendering: Even supported properties may render differently than expected, particularly around font handling, media queries, and box model calculations.
These issues manifest in production as PDF documents that look nothing like their HTML source, with elements stacked vertically instead of in flex layouts, grid items appearing in a single column, and carefully crafted responsive designs collapsing into unusable output.
Error Messages and Symptoms
wkhtmltopdf does not produce error messages for unsupported CSS. The failures are silent:
/* This CSS is completely ignored by wkhtmltopdf */
.container {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20px;
}
.grid-layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 15px;
}
When rendered, developers see:
- Flex containers behave as
display: block - Flex items stack vertically with no spacing
- Grid containers collapse to single-column layouts
-
gap,justify-content,align-itemshave no effect -
grid-template-columnsis completely ignored
<!-- Expected: Three equal columns side by side -->
<!-- Actual: Three items stacked vertically -->
<div class="grid-layout">
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>
Who Is Affected
This issue affects any developer using wkhtmltopdf who relies on modern CSS:
Development Environments:
- All platforms (Windows, Linux, macOS)
- All wkhtmltopdf versions (the WebKit engine is the same across all releases)
- Docker containers using wkhtmltopdf images
- Cloud functions and serverless environments
Use Cases:
- Invoice and report generation with modern layouts
- Converting web applications to PDF
- Generating documentation from HTML templates
- Any workflow using CSS written after 2012
Framework Integration:
- Node.js applications using wkhtmltopdf wrappers
- Python applications with pdfkit
- Ruby on Rails with wicked_pdf or PDFKit gems
- PHP applications using snappy or similar libraries
- .NET applications calling wkhtmltopdf via process execution
The scope of affected users is significant because wkhtmltopdf was once the standard open-source solution for HTML-to-PDF conversion, and many legacy systems still depend on it.
Evidence from the Developer Community
The CSS limitations in wkhtmltopdf have been documented extensively across multiple platforms over many years.
Timeline
| Date | Event | Source |
|---|---|---|
| 2015-03-12 | First Flexbox support request | GitHub Issues |
| 2016-08-19 | Grid layout feature request opened | GitHub Issues |
| 2018-04-22 | WebKit upgrade request marked "help wanted" | GitHub Issues |
| 2020-01-10 | Project declared "archived" status | GitHub Repository |
| 2022-12-15 | Final confirmation: no future updates | Project README |
Community Reports
"Flexbox doesn't work at all. Even simple
display: flexis ignored. Had to rewrite all my templates using float and table layouts like it's 2008."
— Stack Overflow user, 2019"We spent weeks trying different wkhtmltopdf flags and configurations. Nothing works because the underlying WebKit simply doesn't support grid. We ended up switching to a Chromium-based solution."
— GitHub Issues commenter, 2020"The project is dead. Archived. No one is updating the Qt WebKit dependency, so these CSS features will never be supported."
— Reddit r/webdev, 2021
Hundreds of Stack Overflow questions exist with titles like "wkhtmltopdf flexbox not working" and "CSS grid ignored in wkhtmltopdf," all reaching the same conclusion: the feature gaps are permanent.
Root Cause Analysis
The technical explanation for wkhtmltopdf's CSS limitations is straightforward: the rendering engine is obsolete.
Qt WebKit Version: wkhtmltopdf uses a patched version of Qt WebKit that corresponds roughly to Safari 5.x / Chrome 13.x era (2011-2012). This predates:
- CSS Flexbox (standardized 2012, widespread support 2015+)
- CSS Grid (standardized 2017)
- CSS Custom Properties (standardized 2015)
- CSS Shapes, Container Queries, and other modern features
Why No Updates?: Qt deprecated QtWebKit in 2013 in favor of QtWebEngine (based on Chromium). The wkhtmltopdf project continued using the deprecated QtWebKit because QtWebEngine does not support headless rendering in the same way. This architectural decision locked the project into an engine that stopped receiving feature updates.
Project Archived: In 2020, the wkhtmltopdf maintainers officially archived the repository. The README now states:
"This project is archived and is no longer maintained."
This means:
- No new features will be added
- The WebKit engine will never be updated
- CSS Flexbox and Grid will never be supported
- Security vulnerabilities will not be patched
The CSS support gap is not a bug that can be fixed—it's a fundamental limitation of an abandoned project using deprecated technology.
CSS Features That Do Not Work
For reference, here is a comprehensive list of CSS features that wkhtmltopdf does not support or supports incorrectly:
Completely Unsupported
| Feature | CSS Property/Value | Status |
|---|---|---|
| Flexbox | display: flex |
Ignored |
| Flexbox |
flex-direction, flex-wrap
|
Ignored |
| Flexbox |
justify-content, align-items
|
Ignored |
| Flexbox |
flex-grow, flex-shrink, flex-basis
|
Ignored |
| Flexbox |
gap (flex context) |
Ignored |
| Grid | display: grid |
Ignored |
| Grid | grid-template-* |
Ignored |
| Grid |
grid-gap, gap
|
Ignored |
| Grid |
grid-area, grid-column, grid-row
|
Ignored |
| CSS Variables | --custom-property |
Ignored |
| CSS Variables | var() |
Ignored |
| Filters |
filter: blur(), filter: drop-shadow()
|
Ignored |
| Blend Modes | mix-blend-mode |
Ignored |
| Object Fit | object-fit |
Ignored |
| Clip Path | clip-path |
Ignored |
Partially Supported / Buggy
| Feature | Issue |
|---|---|
@font-face |
Works inconsistently; requires specific font formats |
@media print |
Partially recognized; some properties ignored |
transform |
2D transforms partially work; 3D does not |
border-radius |
Works but may clip content incorrectly |
box-shadow |
Works but may cause rendering artifacts |
opacity |
Works but interacts poorly with other properties |
position: sticky |
Ignored |
calc() |
Partial support; complex calculations fail |
Attempted Workarounds
Developers have attempted various workarounds, none of which restore the missing functionality.
Workaround 1: Float-Based Layouts
Approach: Replace Flexbox/Grid with CSS floats and clearfix patterns.
/* Instead of Flexbox */
.container {
overflow: hidden; /* clearfix */
}
.column {
float: left;
width: 33.333%;
box-sizing: border-box;
}
Limitations:
- Requires significant HTML/CSS restructuring
- Vertical centering becomes difficult
- Equal-height columns require hacks
- Cannot replicate many Flexbox/Grid features
- Maintenance nightmare for complex layouts
Workaround 2: Table-Based Layouts
Approach: Use HTML tables or CSS display: table for column layouts.
.table-container {
display: table;
width: 100%;
}
.table-cell {
display: table-cell;
vertical-align: middle;
}
Limitations:
- Semantic HTML concerns
- Limited flexibility compared to Flexbox/Grid
- Cannot wrap or reorder items
- Complex nested structures become unwieldy
Workaround 3: Inline-Block Layouts
Approach: Use display: inline-block with calculated widths.
.inline-container {
font-size: 0; /* Remove whitespace gaps */
}
.inline-item {
display: inline-block;
width: 33.333%;
font-size: 16px; /* Reset font size */
vertical-align: top;
}
Limitations:
- Whitespace handling is fragile
- Vertical alignment is limited
- Cannot achieve many modern layout patterns
- Requires careful width calculations
Workaround 4: Separate Stylesheets
Approach: Maintain two CSS files—one for browsers, one for wkhtmltopdf.
<!-- Browser styles -->
<link rel="stylesheet" href="modern.css" media="screen">
<!-- wkhtmltopdf styles -->
<link rel="stylesheet" href="legacy.css" media="print">
Limitations:
- Double maintenance burden
- Easy for stylesheets to drift out of sync
- Does not solve the fundamental feature gap
- Increases complexity significantly
None of these workarounds address the core issue: wkhtmltopdf cannot render modern CSS, and no amount of configuration or alternative CSS patterns can add features to an obsolete rendering engine.
A Different Approach: IronPDF
For developers who need HTML-to-PDF conversion with full CSS support, IronPDF offers an alternative architecture. IronPDF embeds a Chromium rendering engine—the same engine that powers Google Chrome, Microsoft Edge, and other modern browsers.
Why IronPDF Handles Modern CSS
The architectural difference is significant:
| Aspect | wkhtmltopdf | IronPDF |
|---|---|---|
| Rendering Engine | Qt WebKit (2012) | Chromium (Current) |
| CSS Flexbox | Not Supported | Full Support |
| CSS Grid | Not Supported | Full Support |
| CSS Variables | Not Supported | Full Support |
| JavaScript | Partial | Full V8 Engine |
| Updates | Archived/None | Regular Updates |
IronPDF's Chromium engine supports the same CSS features as Chrome, meaning developers can use modern CSS without modification. The same HTML that renders correctly in Chrome will render identically in IronPDF.
Code Example: Modern CSS Rendering
using IronPdf;
public class ModernCssPdfGenerator
{
public void GeneratePdfWithFlexboxAndGrid()
{
// IronPDF uses Chromium, which fully supports modern CSS
var renderer = new ChromePdfRenderer();
// HTML with Flexbox and Grid layouts
string htmlContent = @"
<!DOCTYPE html>
<html>
<head>
<style>
/* CSS Flexbox - fully supported */
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20px;
padding: 20px;
background: #f5f5f5;
}
.flex-item {
flex: 1;
padding: 15px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* CSS Grid - fully supported */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 15px;
padding: 20px;
}
.grid-item {
padding: 20px;
background: #e0e0e0;
border-radius: 4px;
}
/* CSS Variables - fully supported */
:root {
--primary-color: #2196F3;
--spacing: 16px;
}
.styled-element {
color: var(--primary-color);
margin: var(--spacing);
}
</style>
</head>
<body>
<h1>Modern CSS Layout Demo</h1>
<h2>Flexbox Layout</h2>
<div class='flex-container'>
<div class='flex-item'>Flex Item 1</div>
<div class='flex-item'>Flex Item 2</div>
<div class='flex-item'>Flex Item 3</div>
</div>
<h2>Grid Layout</h2>
<div class='grid-container'>
<div class='grid-item'>Grid Item 1</div>
<div class='grid-item'>Grid Item 2</div>
<div class='grid-item'>Grid Item 3</div>
<div class='grid-item'>Grid Item 4</div>
<div class='grid-item'>Grid Item 5</div>
<div class='grid-item'>Grid Item 6</div>
</div>
<p class='styled-element'>This text uses CSS variables.</p>
</body>
</html>";
// Render with full CSS support
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Save the PDF
pdf.SaveAs("modern-css-layout.pdf");
}
}
Key points about this code:
- The same CSS that works in Chrome works identically in IronPDF
- Flexbox properties like
display: flex,justify-content,align-items, andgaprender correctly - Grid properties like
grid-template-columnsandgrid-gapcreate proper multi-column layouts - CSS custom properties (variables) work with
var()function - No workarounds or legacy fallback CSS required
Converting Existing wkhtmltopdf Projects
For developers migrating from wkhtmltopdf, the process typically involves:
using IronPdf;
public class WkhtmltopdfMigration
{
public void ConvertExistingHtml()
{
var renderer = new ChromePdfRenderer();
// Configure rendering options similar to wkhtmltopdf flags
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
// Paper size (equivalent to --page-size)
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
// Enable background graphics (equivalent to --background)
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
// JavaScript execution timeout
renderer.RenderingOptions.Timeout = 60;
// Render from URL (like wkhtmltopdf url output.pdf)
var pdf = renderer.RenderUrlAsPdf("https://example.com/report");
pdf.SaveAs("converted-report.pdf");
}
}
API Reference
For more details on the methods used:
- ChromePdfRenderer - The primary rendering class
- RenderingOptions - Configuration options for PDF generation
- HTML to PDF Tutorial - Step-by-step guide
Migration Considerations
Licensing
IronPDF is commercial software with a per-developer licensing model. A free trial is available for evaluation. wkhtmltopdf is open-source (LGPL), so moving to IronPDF introduces a licensing cost. For many organizations, the time saved not maintaining legacy CSS workarounds justifies this cost.
API Differences
wkhtmltopdf is typically invoked as a command-line tool or through language-specific wrappers. IronPDF is a native .NET library:
| wkhtmltopdf | IronPDF Equivalent |
|---|---|
wkhtmltopdf input.html output.pdf |
renderer.RenderHtmlFileAsPdf("input.html") |
--page-size A4 |
RenderingOptions.PaperSize = PdfPaperSize.A4 |
--margin-top 10 |
RenderingOptions.MarginTop = 10 |
--javascript-delay 500 |
RenderingOptions.WaitFor.JavaScript(500) |
--no-background |
RenderingOptions.PrintHtmlBackgrounds = false |
What You Gain
- Full CSS Flexbox support
- Full CSS Grid support
- CSS Variables (custom properties)
- Modern JavaScript execution (ES6+)
- Regularly updated rendering engine
- Active development and support
- Security patches
What to Consider
- Commercial licensing required for production
- Larger deployment size than wkhtmltopdf (Chromium is embedded)
- Memory usage is higher during rendering (Chrome process)
- Initial learning curve for IronPDF-specific APIs
Conclusion
wkhtmltopdf's CSS limitations—specifically the complete absence of Flexbox and Grid support—are permanent. The project is archived, the Qt WebKit engine is obsolete, and no updates are forthcoming. Developers requiring modern CSS rendering in PDF generation need to migrate to a solution built on a current rendering engine. IronPDF, with its embedded Chromium engine, renders CSS exactly as modern browsers do, eliminating the need for legacy workarounds.
Jacob Mellor is CTO at Iron Software and the original developer of IronPDF.
References
- wkhtmltopdf GitHub Repository (Archived){:rel="nofollow"} - Official project repository showing archived status
- Qt WebKit Deprecation Notice{:rel="nofollow"} - Qt's documentation on WebKit deprecation
- CSS Flexbox Specification{:rel="nofollow"} - W3C Flexbox standard (2017)
- CSS Grid Specification{:rel="nofollow"} - W3C Grid standard (2017)
- Stack Overflow: wkhtmltopdf flexbox{:rel="nofollow"} - Community questions about Flexbox support
For the latest IronPDF documentation and tutorials, visit ironpdf.com.
Top comments (0)