HTMLtoPDFWidgets 🚀
Build Professional PDFs from HTML & Markdown with Pixel-Perfect Precision
htmltopdfwidgets is a high-performance rendering engine designed for Flutter and Dart. It goes beyond simple tag mapping, providing a Layout-First pipeline that mimics browser rendering to ensure your PDFs look exactly like your web content.
Tip
AI-Ready Documentation: If you're using an AI assistant (like Claude, GPT, or Copilot) to help with this repository, point it to llm.txt for a deep dive into the architecture and logic.
❤️ Support the Core Maintainer
If this project saves you time, consider buying me a coffee! It helps keep the development alive and the energy high.
🌟 Why htmltopdfwidgets?
Generating PDFs from HTML is often messy. This package solves that by introducing a Browser-Grade Rendering Pipeline.
- 🎯 Precision Scaling: Automatically scales $1px$ to $0.75pt$, matching the industry standard for High-DPI PDF generation.
- 🔳 Full Box Model: Respects
width,height,padding,margin, andborderwith CSS-like cascading. - 🏗️ Native Flexbox: Turn
display: flexrows and columns into native PDF widgets seamlessly. - 📄 Advanced Pagination: Intelligent content breaking prevents text clipping and ensures tables break gracefully across pages.
- 🖼️ Media Ready: Handles network images, local files, and custom SVG paths.
🛠️ How it Works (The Pipeline)
Our new Layout-First architecture ensures consistent results across all document types.
graph LR
A[HTML/MD String] --> B[HtmlParser]
B --> C[RenderNode Tree]
C --> D[LayoutSolver]
D --> E[LayoutNode Tree]
E --> F[PdfBuilder]
F --> G[PDF Widgets]
style D fill:#f9f,stroke:#333,stroke-width:2px
style F fill:#bbf,stroke:#333,stroke-width:2px
🚀 Installation
Add it to your pubspec.yaml:
dependencies:
htmltopdfwidgets: ^2.2.0
📖 Usage Guide
📂 Using the Modern Browser Engine (Recommended)
The modern engine is built for accuracy and complex CSS.
import 'package:htmltopdfwidgets/htmltopdfwidgets.dart';
final String htmlContent = '''
<div style="padding: 24px; background-color: #f8f9fa; border: 2px solid #007bff; border-radius: 8px;">
<h1 style="color: #007bff; text-align: center;">Invoicing Simplified</h1>
<div style="display: flex; flex-direction: row; justify-content: space-between; margin-top: 20px;">
<div style="flex-grow: 1;">
<p><b>Client:</b> John Doe</p>
<p><b>Date:</b> April 16, 2024</p>
</div>
<div style="width: 150px; text-align: right;">
<p style="font-size: 24px;">$1,250.00</p>
</div>
</div>
</div>
''';
void main() async {
final widgets = await HTMLToPdf().convert(
htmlContent,
useNewEngine: true, // Unleash the Layout-First power
);
final pdf = Document();
pdf.addPage(MultiPage(build: (context) => widgets));
// Save or preview your PDF
}
📝 Markdown to PDF
Directly convert Markdown rich text into structured PDF documents.
final markDown = '''
# 📖 Project Documentation
---
> Building better PDFs together.
### Features
- [x] High-performance rendering
- [x] **Flexbox** support
- [x] Custom font fallbacks
''';
final List<Widget> widgets = await HTMLToPdf().convertMarkdown(markDown);
🎨 Advanced Features
🌈 Custom Styling
Override any tag's default style with a single object.
final widgets = await HTMLToPdf().convert(
html,
tagStyle: HtmlTagStyle(
h1Style: pw.TextStyle(color: PdfColors.blue900, fontWeight: pw.FontWeight.bold),
pStyle: pw.TextStyle(lineSpacing: 2.0),
),
);
🌍 Global Language Support & Emojis
Using fontFallback allows you to render Emojis and non-Latin scripts (Arabic, Kanji, etc.) effortlessly.
final widgets = await HTMLToPdf().convert(
'Success! 🚀 ✅ Done.',
fontFallback: [emojiFont, mainFont],
);
📦 Tag Support Matrix
| Category | Supported Elements |
|---|---|
| Typography | h1-h6, p, span, b, strong, i, em, u, ins, s, del, sub, sup, small, big, cite, kbd, font, center, br, hr, code, pre |
| Containers | div, section, article, header, footer, nav, aside, main |
| Lists | ul, ol (type, start, reversed), li (value), dl, dt, dd |
| Layout | table, caption, thead, tbody, tr, th, td, blockquote |
| Interactive | a (links), input[type="checkbox"] |
| Media | img (Base64, Network, File) |
| Math (MathML) | math (inline, or display="block"), mfrac, msup, msub, msubsup, msqrt, mroot, munder, mover, munderover, mfenced, mtable/mtr/mtd, mi, mn, mo, mtext, mspace, mrow, semantics |
Tables
Tables follow browser layout:
colspanandrowspan. A tall spanning cell spreads its extra height over the rows it covers, and a page never breaks inside a rowspan group.- Block content in cells (paragraphs, lists, images), cell and row CSS borders and backgrounds.
valign/vertical-align,cellpaddingand cellpadding, explicit column widths.<thead>rows repeat at the top of every page the table continues on.border="0"orborder: noneremoves the grid.
CSS
<style>blocks support descendant, child and sibling combinators, attribute selectors, structural pseudo-classes (:first-child,:nth-child(odd)), specificity and!important.- Colors: all 148 CSS named colors,
#rgb/#rgba/#rrggbbaa,rgb()/rgba(),hsl()/hsla(). - Box model:
margin-*,padding-*, per-side borders,background, and vertical margin collapsing as in browsers. - Text: the
fontshorthand,em/%/keyword font sizes, numericfont-weight,line-height,letter-spacing,text-transform,white-space,vertical-align: super/sub, andmm/cm/pc/ex/chunits.
MathML
Sum, product and integral signs and radicals are drawn as vector shapes, so they work with any font. Other symbols outside Latin-1 (Greek letters, ≤, →, ...) need a font that has them, passed via fontFallback; without one they fall back to readable text (pi, <=, ->).
🤝 Contributing
We love contributions! If you have an idea to make this engine even more powerful, please:
- Fork the repo.
- Create your feature branch.
- Submit a PR!
License: MIT | Maintainer: Ali Hassan