HTML output
byte[] html = document.RenderAsHtml();File.WriteAllBytes("invoice.html", html);HTML output is a single self-contained file: semantic markup, a deduplicated <style> block,
and images embedded as base64 data: URIs. Nothing links out, so you can email it, drop it into a
web page, or open it straight from disk.
It is a reflowable document, not a picture of a printed page. Text wraps to the reader’s window, and the browser paginates when printing. If you need an exact fixed-page rendering, use PDF.
What the file looks like
Section titled “What the file looks like”<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Quarterly Report</title><style>@page{size:595pt 842pt;margin:36pt 36pt 36pt 36pt}.pp-page{width:595pt;padding:36pt 36pt 36pt 36pt}.pp-t1{font-size:18pt;font-weight:700}</style></head><body><div class="pp-doc"><div class="pp-page"><header class="pp-band pp-band-header"><p>Acme Ltd</p></header><div class="pp-body"><p class="pp-p1"><span class="pp-t1">Quarterly Report</span></p></div></div></div></body></html>Every class carries a pp- prefix, so the markup will not collide with a host page’s styles if you
lift the body out. Styles are deduplicated: a style used on a thousand runs is written once.
Elements that use only the defaults carry no class at all - the reset already encodes them (10pt Arial, a 1.2 line-height, 4pt cell padding, a 24pt list indent), because those are the same values the layout engine uses.
Page size and margins
Section titled “Page size and margins”Page setup maps twice - a container width for the screen, and an @page rule for printing:
doc.PageSize(PageSize.A4).Margin(36f);On screen you get a 595pt-wide page-shaped container. When the reader prints (or saves to PDF from
the browser), @page supplies the sheet size and margins, and the container’s own padding is reset
so the two never add up. A document without a PageSize gets a plain 800pt-wide container and no
@page rule at all.
Sections each become their own container with their own named @page, so a
landscape appendix prints landscape.
Printing to PDF from the browser
Section titled “Printing to PDF from the browser”Open the file and print. The @page rule gives the correct sheet size and margins, <thead> and
<tfoot> rows repeat on every page, and page breaks and keep-together hints are honored via
break-before / break-inside.
This is a convenience, not a replacement for OutputFormat.Pdf - the browser wraps text with its
own font metrics, so line breaks and page counts differ from Papyra’s PDF output.
What HTML does better than the other formats
Section titled “What HTML does better than the other formats”- Real font weights.
FontWeight.LightthroughBLACKmap to CSSfont-weight: 300…900. DOCX and XLSX collapse everything to a bold flag. - True alpha. Translucent colors emit
rgba(). DOCX has no alpha channel and blends onto white. - Repeating table footers.
<tfoot>repeats on every printed page; OOXML has no equivalent, so DOCX can only repeat headers. - Per-sub-list numbering. Each nested list keeps its own format. Word allows one configuration per level within a numbering definition, so DOCX cannot express sibling sub-lists that differ.
Limitations
Section titled “Limitations”- Headers and footers render once per section, at the top and bottom of the flow - not repeated on every printed page. One container per printed page is not possible: the browser re-wraps with its own metrics, so Papyra’s page breaks would put content in the wrong container.
- Page-number fields are omitted. A reflowable document has no page count, and the CSS Paged
Media counters that could supply one when printing are not implemented by Chrome or Firefox. A
PageXofY()footer therefore renders its literal text without the numbers - in bands and in body paragraphs alike.RenderDate()works normally - it has a definite value. - Custom fonts are named, not embedded. Fonts registered with
RegisterFontare embedded in PDF output only; HTML emits the family name with an Arial fallback, so install the font or use a web font in the host page. See fonts. - File size. A 2 MB logo becomes roughly 2.7 MB of base64. Self-contained output is the trade-off.
- Adjacent cell borders collapse. A cell without its own left border still shows its neighbour’s right border, and when two cells give a shared edge different styles the browser picks one by CSS precedence (dashed beats dotted beats solid at equal widths). PDF strokes each edge independently.
- Watermarks stamp once per section container, and an auto-sized watermark’s font size is approximated (the browser cannot be asked to measure text before layout).
- There are no HTML-specific render options yet.
© 2026 Stefan Nikolei. Payments are processed by Paddle.com as merchant of record.