npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-print-pdf

v0.3.0

Published

Browser-side React to vector PDF from the live DOM. Tailwind v4, fonts, pagination, images, and raster fallback.

Readme

react-print-pdf

Browser-side React → vector PDF. Reads computed styles from the live DOM so Tailwind v4, CSS-in-JS, and design tokens work without a second layout system.

react-print-pdf exports an already-rendered React document to PDF in the browser. It walks the mounted DOM, reads layout and computed styles, paginates primitives, and emits a PDF with pdf-lib.

Status

Public release. Current version: 0.2.0 on npm under the latest dist-tag.

  • Browser-only for v1
  • React-only public integration
  • MIT licensed
  • Docs site: docs/

Install

npm install react-print-pdf

Try it in your browser without cloning:

https://stackblitz.com/github/hempun10/react-print-pdf/tree/main/examples/starter

Quick start

react-print-pdf ships two ways to drive an export. Both call the same pipeline; pick whichever fits your call site.

Hook + Printable (recommended for React apps)

import { Printable, usePDFExport } from "react-print-pdf";

export function InvoiceExport() {
  const { ref, exportPDF, isExporting, error } = usePDFExport({
    format: "A4",
    margin: "20mm",
    filename: "invoice.pdf",
    title: "Invoice #1042",
  });

  return (
    <>
      <button onClick={exportPDF} disabled={isExporting}>
        {isExporting ? "Exporting…" : "Export PDF"}
      </button>
      {error && <p role="alert">{error.message}</p>}
      <Printable ref={ref} format="A4" margin="20mm">
        <Invoice />
      </Printable>
    </>
  );
}

<Printable> sizes itself to the PDF page automatically. usePDFExport owns the ref, loading state, error state, and result handle. By default it calls result.save() for you on success; pass autoSave: false and read lastResult for upload-only flows.

Functional (use it from anywhere)

exportToPDF takes a mounted HTMLElement. In React, render your printable document normally and pass ref.current.

import { useRef } from "react";
import { exportToPDF, PageBreak, registerFont } from "react-print-pdf";

export function InvoiceExport() {
  const printRef = useRef<HTMLDivElement>(null);

  async function exportInvoice() {
    if (!printRef.current) return;

    await registerFont({
      family: "Inter",
      src: "/fonts/Inter-Regular.ttf",
      weight: 400,
    });

    const result = await exportToPDF(printRef.current, {
      format: "A4",
      margin: "20mm",
      filename: "invoice.pdf",
      title: "Invoice #1042",
      header: ({ pageNumber, totalPages }) => (
        <div className="text-xs text-gray-500">
          Page {pageNumber} / {totalPages}
        </div>
      ),
      onPageRendered: (n, total) => console.log(`rendered ${n}/${total}`),
    });

    result.save();
  }

  return (
    <>
      <button type="button" onClick={exportInvoice}>
        Export PDF
      </button>

      <div ref={printRef} style={{ width: 640 }}>
        <Invoice />
        <PageBreak />
        <Appendix />
      </div>
    </>
  );
}

Use the returned handle directly when you do not want an immediate download:

const result = await exportToPDF(printRef.current, options);

result.save();
result.save("copy.pdf");
result.preview();
const bytes = result.bytes();
const blob = result.blob();

Why not Puppeteer or @react-pdf/renderer?

Headless Chromium is accurate, but it is server-side infrastructure: a large binary, cold starts, operational work, and privacy questions for user documents.

@react-pdf/renderer is useful when you want a React-like PDF-only layout tree, but it asks you to rebuild your UI with <Document>, <Page>, <View>, and <Text> primitives plus a smaller CSS subset.

react-print-pdf takes a third path: the browser remains the layout engine. Your existing React/Tailwind/CSS-in-JS document renders normally, then the library captures the computed result and emits PDF primitives.

What works in 0.2

  • DOM layout capture via getBoundingClientRect() and computed styles
  • Text from Range.getClientRects()
  • Registered TTF/OTF fonts with browser FontFace loading and PDF embedding
  • CSS colors, including Tailwind v4 oklch() colors through browser resolution
  • Solid backgrounds and borders, including per-side colors and rounded corners
  • True alpha — semi-transparent fills/borders compose against underlying content correctly (ExtGState)
  • Soft card backgrounds that continue across page breaks (rounded corners only at the start and end of the run)
  • Hyperlinks<a href> becomes a clickable PDF Link annotation, including links that wrap onto multiple lines
  • Explicit page breaks with <PageBreak />
  • Automatic pagination by page content height
  • CSS break-before / break-after (page / always / left / right, plus the legacy page-break-* aliases)
  • break-inside: avoid with overflow warnings when an item taller than a page is asked to stay together
  • Headers and footers rendered per page with { pageNumber, totalPages }
  • Repeating bands with data-print-repeat, typically for table headers
  • PNG/JPEG <img> embedding from data URLs, same-origin URLs, blob URLs, and CORS-permitted remote URLs
  • Raster fallback for gradients, shadows, transforms, filters, SVG, and manual data-pdf-raster="true" regions
  • Typed errorsPdfExportError with code + cause, plus an isPdfExportError(e) guard
  • Lifecycle hooksonProgress(stage, pct) for the five-stage pipeline, onPageRendered(pageNumber, totalPages) for per-page callbacks
  • Debug overlaydebug: true paints colored outlines + labels on every emitted primitive's box
  • React DX layerusePDFExport hook, <Printable> auto-sized container, and <ExportButton> for the simple case

Current limitations

  • Browser-only; no Node/SSR export path yet
  • Source DOM should fit the PDF content width (640px is a safe A4 + 20mm margin starting point)
  • Fonts must be TTF or OTF; WOFF/WOFF2 cannot be embedded by pdf-lib
  • object-fit on images is not honored yet
  • Text decoration, text shadow, letter spacing, and word spacing are incomplete
  • SVG is rasterized, not emitted as PDF vector paths
  • Soft card backgrounds with mixed-color borders fall back to the legacy atomic-rect path

See docs/content/docs/limitations.mdx for the full list.

Demo

cd examples/demo
npm install
npm run dev

Open the Vite URL and click Export PDF. The demo includes invoices, long tables, cards, text fixtures, raster effects, and image embedding.

Starter

A minimal Vite + React + react-print-pdf app lives at examples/starter. Open it directly in StackBlitz:

https://stackblitz.com/github/hempun10/react-print-pdf/tree/main/examples/starter

Or run locally:

cd examples/starter
npm install
npm run dev

Docs site

Production docs and landing page: https://react-print-pdf-inky.vercel.app

Live component gallery ("workshop"): https://react-print-pdf-workshop.vercel.app

Run the docs locally:

cd docs
npm install
npm run dev   # http://localhost:3001

The docs app is a separate Next.js + Fumadocs project under docs/. See docs/DEPLOY.md for the Vercel + GitHub Actions wiring.

Development

npm install
npm run lint
npm run typecheck
npm run test
npm run build

Visual/demo coverage lives under examples/demo and Playwright configs.

License

MIT