PDFreact-print-pdf
DocsBrowser-only alpha

Introduction

Export the React you've already built to a real vector PDF — no headless browser, no second component language.

Edit this page

You've already built the screen. Your invoice, statement, receipt, or report renders in the browser, looks the way the designer drew it, prints from Chrome, and your QA team has stopped filing tickets about it.

Then product says: "can users download a PDF?"

That single feature usually triggers one of three sad architectures: spin up a Chromium fleet on the server and pray it doesn't OOM; rebuild the whole document in a parallel renderer with its own CSS subset; or screenshot the screen to a canvas and ship a fuzzy image where the text used to be selectable.

react-print-pdf is the fourth option. It takes the DOM the browser already painted and emits a real vector PDF in the same tab — selectable text, embedded fonts, hyperlinks, the works. No server, no second renderer, no canvas blur.

The five stages from React render to PDF bytes
The five stages from React render to PDF bytesReact<Invoice />renders normallylive DOMrects + computedstyles + fontswalktext · bordersimages · rasterpaginateslice by pagerepeat header / footerPDFbytes(download)1. you write2. browser paints3. we capture4. split pages5. emitthe browser is the layout engine
The browser stays the layout engine. react-print-pdf reads what it painted, walks every box, and emits PDF primitives via pdf-lib.

What this is

A small library that:

  • runs in the browser (no Node, no server fleet)
  • reads the DOM your existing React component already laid out
  • emits PDF primitives via pdf-lib — selectable text, embedded TTF/OTF fonts, real PNG/JPEG images, real hyperlinks
  • handles pagination, repeating headers and footers, manual page breaks
  • falls back to raster for the handful of effects that don't translate cleanly (gradients, shadows, filters, SVG roots)
  • ships React DX: a usePDFExport hook, a <Printable> wrapper, an <ExportButton>

It does not:

  • ask you to rewrite anything
  • need its own component language
  • require a server
  • give up on selectable text because of a single drop shadow

Why bother

Most teams arrive at PDF after they already own a document UI: React components, Tailwind utilities, design tokens, branded tables, typography rules. Throwing that work away to "do PDF properly" is the most expensive option, not the cleanest.

Here's how the common paths trade off:

Tooling pathWhat you getWhat you pay
Headless ChromiumAccurate screenshots or print outputServer fleet, cold starts, ~200MB binaries, operational overhead
Parallel renderers (e.g. @react-pdf/renderer)Browser-independent PDF generationA second layout/component system and a smaller CSS subset
Canvas screenshot exportVisual fidelityBlurry text, no selection, large files, inaccessible output
react-print-pdfBrowser layout + vector PDF primitivesBrowser-only for v1, plus a short list of honest limitations

How it actually works

Five stages. You only write the first one — the browser does stage two for free, we do stages three through five.

  1. You render. A regular React component. Tailwind, CSS modules, whatever you already use.
  2. The browser paints. Computed styles, font metrics, line wrapping, table layout — already solved, already in the DOM.
  3. We walk. We read every box, every text rectangle, every image, every border, and tag the regions that need raster fallback.
  4. We paginate. Split the captured tree into pages, repeat your header and footer, honor break-before / break-after / break-inside: avoid.
  5. We emit. pdf-lib does the byte serialization, fonts get subset, images get embedded, links become clickable annotations.

Want the longer version with examples? Read How it works. Want to ship something today? Quick start takes three minutes.

What's vector today

Everything the browser draws with shapes and text, we draw with shapes and text:

  • text runs from Range.getClientRects() — exactly where the browser put them
  • solid backgrounds, including ones that continue across page breaks
  • borders, including per-side colors and rounded corners
  • hyperlinks: every <a href> becomes a clickable PDF Link annotation
  • PNG and JPEG images as PDF image XObjects (real bytes, not screenshots)
  • registered TTF/OTF fonts, subset into the final PDF
  • pagination, headers, footers, explicit breaks, repeat bands
  • true alpha — semi-transparent fills compose correctly against everything underneath

What falls back to raster

Some browser effects are expensive or unreliable to recreate as PDF vectors. The library automatically captures those regions as PNGs at high DPI:

  • gradients
  • shadows
  • CSS transforms
  • filters
  • SVG roots
  • anything you tag manually with data-pdf-raster="true"

The goal isn't ideological purity — it's a PDF that stays mostly vector while preserving the parts the browser can draw better than a hand-rolled PDF emitter could.

Status

Public, MIT-licensed, semver-stable from 0.2.0.

  • Current channel: 0.2.0 on npm under the latest dist-tag
  • Scope: browser-only, React-only for v1
  • API shape: pass an HTMLElement to exportToPDF, or use the React DX layer (usePDFExport, <Printable>, <ExportButton>)
  • Honest about gaps: the Limitations page is short, current, and not buried

Where to next

If you want toGo here
See it work in three minutesQuick start
Understand the export pipelineHow it works
Copy a real-world exampleExamples
Know what to avoid before productionBest practicesLimitations
Wire your AI coding toolAI guide

On this page