react-pdf

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Generating PDFs with React-PDF

使用React-PDF生成PDF

CRITICAL REQUIREMENTS

关键要求

  1. Fonts MUST be local files - Remote font URLs (http/https) do NOT work. Always download fonts to local files before using them.
  2. Wrap async code in IIFE - Top-level await causes errors. Always use
    (async () => { ... })()
    pattern.
  3. Disable hyphenation for custom fonts - Custom fonts lack hyphenation dictionaries and may crash or break words incorrectly. Always call
    Font.registerHyphenationCallback((word) => [word]);
    after registering custom fonts.
  1. 字体必须是本地文件 - 远程字体URL(http/https)无法使用。使用前务必将字体下载到本地文件。
  2. 将异步代码包裹在IIFE中 - 顶层await会导致错误。务必使用
    (async () => { ... })()
    模式。
  3. 为自定义字体禁用断字功能 - 自定义字体缺少断字词典,可能会崩溃或错误拆分单词。注册自定义字体后务必调用
    Font.registerHyphenationCallback((word) => [word]);

Files

文件

  • references/google-fonts.txt
    - Metadata for ~65 popular Google Fonts with TrueType URLs. Each line is a font variant in tab-separated format:
    font name
    ,
    style
    ,
    category
    ,
    weight
    ,
    url
    .
  • references/components.md
    - Full component API reference and supported CSS properties
  • assets/example-template.tsx
    - Minimal working example demonstrating fixed footers, page numbers, and unbreakable content. Read this before starting to understand the basic patterns. Note: not all APIs are shown here — always refer to the docs and
    references/components.md
    for the full API.
  • references/google-fonts.txt
    - 约65种热门Google Fonts的元数据,包含TrueType URL。每行是一个字体变体,采用制表符分隔格式:
    字体名称
    样式
    类别
    字重
    URL
  • references/components.md
    - 完整的组件API参考和支持的CSS属性
  • assets/example-template.tsx
    - 展示固定页脚、页码和不可拆分内容的最简可用示例。开始前请阅读此示例以了解基本模式。注意:此处未展示所有API — 如需完整API,请始终参考文档和
    references/components.md

Prerequisites

前置依赖

bash
npm install react @react-pdf/renderer
npm install -D tsx @types/react
tsx
runs TypeScript + JSX files directly via Node with no config — no
tsconfig.json
needed. It uses esbuild under the hood and handles JSX transformation automatically.
bash
npm install react @react-pdf/renderer
npm install -D tsx @types/react
tsx
可直接通过Node运行TypeScript + JSX文件,无需配置 — 不需要
tsconfig.json
。它在底层使用esbuild,可自动处理JSX转换。

Core Components

核心组件

  • Document: Root component (metadata, settings)
  • Page: Individual pages (A4, Letter, or custom dimensions)
  • View: Container component (similar to div)
  • Text: Text content, supports nesting for inline styling
  • Image: Embed images (JPG, PNG, base64)
  • Link: Clickable hyperlinks (external or internal)
  • Note: Annotation notes
  • Canvas: Freeform drawing with pdfkit methods
  • Svg: Vector graphics (Circle, Rect, Path, Line, Polygon, etc.)
  • StyleSheet: Create reusable styles
For full component props and CSS properties, see references/components.md.
  • Document:根组件(元数据、设置)
  • Page:单个页面(A4、Letter或自定义尺寸)
  • View:容器组件(类似div)
  • Text:文本内容,支持嵌套以实现内联样式
  • Image:嵌入图片(JPG、PNG、base64)
  • Link:可点击的超链接(外部或内部)
  • Note:注释笔记
  • Canvas:使用pdfkit方法进行自由绘制
  • Svg:矢量图形(Circle、Rect、Path、Line、Polygon等)
  • StyleSheet:创建可复用样式
如需完整的组件属性和CSS属性,请查看references/components.md

Basic Example

基础示例

tsx
import React from "react";
import { Document, Page, Text, View, StyleSheet, renderToFile } from "@react-pdf/renderer";

const styles = StyleSheet.create({
  page: { flexDirection: "column", backgroundColor: "#ffffff", padding: 40 },
  title: { fontSize: 24, marginBottom: 20, fontWeight: "bold" },
  text: { fontSize: 12, lineHeight: 1.5 },
});

const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={{ margin: 10, padding: 20 }}>
        <Text style={styles.title}>Document Title</Text>
        <Text style={styles.text}>Your content here</Text>
      </View>
    </Page>
  </Document>
);

(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
  console.log("PDF saved!");
})();
tsx
import React from "react";
import { Document, Page, Text, View, StyleSheet, renderToFile } from "@react-pdf/renderer";

const styles = StyleSheet.create({
  page: { flexDirection: "column", backgroundColor: "#ffffff", padding: 40 },
  title: { fontSize: 24, marginBottom: 20, fontWeight: "bold" },
  text: { fontSize: 12, lineHeight: 1.5 },
});

const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={{ margin: 10, padding: 20 }}>
        <Text style={styles.title}>Document Title</Text>
        <Text style={styles.text}>Your content here</Text>
      </View>
    </Page>
  </Document>
);

(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
  console.log("PDF saved!");
})();

Running Scripts

运行脚本

PDF generation scripts use JSX, which Node cannot run directly. Use
tsx
to execute them:
bash
npx tsx my-document.tsx
npx tsx
works without installing tsx globally — it downloads on demand. If tsx is installed as a dev dependency (
npm install -D tsx
), it runs instantly without the npx download step.
Always wrap rendering in async IIFE:
tsx
// Good
(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
})();

// Bad - top-level await may fail
await renderToFile(<MyDocument />, "./output.pdf");
PDF生成脚本使用JSX,Node无法直接运行。使用
tsx
执行脚本:
bash
npx tsx my-document.tsx
npx tsx
无需全局安装tsx即可使用 — 它会按需下载。如果tsx已作为开发依赖安装(
npm install -D tsx
),则无需npx下载步骤,可立即运行。
务必将渲染代码包裹在异步IIFE中:
tsx
// 正确写法
(async () => {
  await renderToFile(<MyDocument />, "./output.pdf");
})();

// 错误写法 - 顶层await可能失败
await renderToFile(<MyDocument />, "./output.pdf");

Previewing PDFs

预览PDF

To visually inspect generated PDFs, convert pages to images. Try
pdftoppm
first (often pre-installed), fall back to Python's PyMuPDF if unavailable.
Option 1: pdftoppm (poppler-utils) — preferred, no install needed in many environments:
bash
pdftoppm -png -r 200 document.pdf preview
如需可视化检查生成的PDF,可将页面转换为图片。优先尝试
pdftoppm
(通常已预装),若不可用则 fallback 到Python的PyMuPDF。
选项1:pdftoppm(poppler-utils) — 首选,许多环境中无需安装:
bash
pdftoppm -png -r 200 document.pdf preview

→ preview-1.png, preview-2.png, ...

→ preview-1.png, preview-2.png, ...


**Option 2: PyMuPDF (Python)** — fallback if pdftoppm is not available:

```bash
pip install pymupdf
python
import fitz

doc = fitz.open("document.pdf")
for i, page in enumerate(doc):
    pix = page.get_pixmap(dpi=200)
    pix.save(f"page-{i+1}.png")

**选项2:PyMuPDF(Python)** — 若pdftoppm不可用则使用此备选方案:

```bash
pip install pymupdf
python
import fitz

doc = fitz.open("document.pdf")
for i, page in enumerate(doc):
    pix = page.get_pixmap(dpi=200)
    pix.save(f"page-{i+1}.png")

Rendering Methods

渲染方法

tsx
import { renderToFile, renderToBuffer } from "@react-pdf/renderer";

// To file
(async () => {
  await renderToFile(<MyDocument />, "./document.pdf");
})();

// To buffer
(async () => {
  const buffer = await renderToBuffer(<MyDocument />);
})();
tsx
import { renderToFile, renderToBuffer } from "@react-pdf/renderer";

// 渲染到文件
(async () => {
  await renderToFile(<MyDocument />, "./document.pdf");
})();

// 渲染到缓冲区
(async () => {
  const buffer = await renderToBuffer(<MyDocument />);
})();

Styling

样式设置

Three methods:
StyleSheet.create()
, inline objects, or mixed arrays.
tsx
const styles = StyleSheet.create({ container: { padding: 20 } });

<View style={styles.container} />
<View style={{ padding: 20 }} />
<View style={[styles.container, { marginTop: 10 }]} />
三种方式:
StyleSheet.create()
、内联对象或混合数组。
tsx
const styles = StyleSheet.create({ container: { padding: 20 } });

<View style={styles.container} />
<View style={{ padding: 20 }} />
<View style={[styles.container, { marginTop: 10 }]} />

Supported Units

支持的单位

pt
(default, 72 DPI),
in
,
mm
,
cm
,
%
,
vw
,
vh
pt
(默认,72 DPI)、
in
mm
cm
%
vw
vh

Common Style Properties

常见样式属性

tsx
{
  // Flexbox
  flexDirection: "row", justifyContent: "space-between", alignItems: "center",
  flexWrap: "wrap", gap: 10,

  // Box model
  margin: 10, padding: 20, width: "100%", height: 200,

  // Borders
  borderWidth: 1, borderColor: "#333", borderRadius: 5, borderStyle: "solid",

  // Colors
  backgroundColor: "#f0f0f0", color: "#000", opacity: 0.8,

  // Typography
  fontSize: 12, fontWeight: "bold", fontFamily: "Helvetica", fontStyle: "italic",
  lineHeight: 1.5, textAlign: "center", textDecoration: "underline",
  textTransform: "uppercase", letterSpacing: 1,

  // Position
  position: "absolute", top: 0, left: 0, right: 0, bottom: 0, zIndex: 10,

  // Transforms
  transform: "rotate(45deg)", transformOrigin: "center",
}
tsx
{
  // Flexbox
  flexDirection: "row", justifyContent: "space-between", alignItems: "center",
  flexWrap: "wrap", gap: 10,

  // 盒模型
  margin: 10, padding: 20, width: "100%", height: 200,

  // 边框
  borderWidth: 1, borderColor: "#333", borderRadius: 5, borderStyle: "solid",

  // 颜色
  backgroundColor: "#f0f0f0", color: "#000", opacity: 0.8,

  // 排版
  fontSize: 12, fontWeight: "bold", fontFamily: "Helvetica", fontStyle: "italic",
  lineHeight: 1.5, textAlign: "center", textDecoration: "underline",
  textTransform: "uppercase", letterSpacing: 1,

  // 定位
  position: "absolute", top: 0, left: 0, right: 0, bottom: 0, zIndex: 10,

  // 变换
  transform: "rotate(45deg)", transformOrigin: "center",
}

Images

图片

Local files are most reliable. Remote URLs may fail due to network/CORS issues.
tsx
import { Image } from '@react-pdf/renderer';

<Image src="./images/photo.jpg" style={{ width: 200, height: 150 }} />
<Image src={{ data: buffer, format: 'png' }} />
SVG files cannot be used as Image sources. Read the SVG source and recreate using react-pdf Svg components.
本地文件最可靠。远程URL可能因网络/CORS问题失败。
tsx
import { Image } from '@react-pdf/renderer';

<Image src="./images/photo.jpg" style={{ width: 200, height: 150 }} />
<Image src={{ data: buffer, format: 'png' }} />
SVG文件不能作为Image组件的源。请读取SVG源码并使用react-pdf的Svg组件重新创建。

SVG Graphics

SVG图形

tsx
import { Svg, Circle, Rect, Path, Line, G, Defs, LinearGradient, Stop } from "@react-pdf/renderer";

<Svg width="200" height="200" viewBox="0 0 200 200">
  <Defs>
    <LinearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <Stop offset="0%" stopColor="#3498db" />
      <Stop offset="100%" stopColor="#9b59b6" />
    </LinearGradient>
  </Defs>
  <Circle cx="100" cy="100" r="50" fill="url(#grad1)" />
  <Rect x="10" y="10" width="50" height="50" fill="#e74c3c" />
  <Path d="M10,50 Q50,10 90,50" stroke="#2ecc71" strokeWidth="2" fill="none" />
</Svg>;
tsx
import { Svg, Circle, Rect, Path, Line, G, Defs, LinearGradient, Stop } from "@react-pdf/renderer";

<Svg width="200" height="200" viewBox="0 0 200 200">
  <Defs>
    <LinearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <Stop offset="0%" stopColor="#3498db" />
      <Stop offset="100%" stopColor="#9b59b6" />
    </LinearGradient>
  </Defs>
  <Circle cx="100" cy="100" r="50" fill="url(#grad1)" />
  <Rect x="10" y="10" width="50" height="50" fill="#e74c3c" />
  <Path d="M10,50 Q50,10 90,50" stroke="#2ecc71" strokeWidth="2" fill="none" />
</Svg>;

Using Icons

使用图标

Read SVG source from icon libraries and convert to react-pdf Svg components:
bash
npm install lucide-static
tsx
import { Svg, Path, Rect } from "@react-pdf/renderer";

// Converted from lucide-static/icons/mail.svg
const MailIcon = ({ size = 12, color = "#888" }) => (
  <Svg width={size} height={size} viewBox="0 0 24 24">
    <Path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" stroke={color} strokeWidth={2} fill="none" />
    <Rect x="2" y="4" width="20" height="16" rx="2" stroke={color} strokeWidth={2} fill="none" />
  </Svg>
);
从图标库读取SVG源码并转换为react-pdf的Svg组件:
bash
npm install lucide-static
tsx
import { Svg, Path, Rect } from "@react-pdf/renderer";

// 从lucide-static/icons/mail.svg转换而来
const MailIcon = ({ size = 12, color = "#888" }) => (
  <Svg width={size} height={size} viewBox="0 0 24 24">
    <Path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" stroke={color} strokeWidth={2} fill="none" />
    <Rect x="2" y="4" width="20" height="16" rx="2" stroke={color} strokeWidth={2} fill="none" />
  </Svg>
);

Links and Navigation

链接与导航

tsx
<Link src="https://example.com"><Text>Visit website</Text></Link>

<View id="section-1"><Text>Target</Text></View>
<Link src="#section-1"><Text>Jump to Section 1</Text></Link>
tsx
<Link src="https://example.com"><Text>Visit website</Text></Link>

<View id="section-1"><Text>Target</Text></View>
<Link src="#section-1"><Text>Jump to Section 1</Text></Link>

Dynamic Content and Page Numbers

动态内容与页码

tsx
<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />
tsx
<Text render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`} />

Fixed Headers/Footers

固定页眉/页脚

tsx
<Page size="A4">
  <View fixed style={{ position: "absolute", top: 20, left: 30, right: 30 }}>
    <Text>Header</Text>
  </View>
  <View style={{ marginTop: 60, marginBottom: 60 }}>
    <Text>Content</Text>
  </View>
  <Text
    fixed
    style={{ position: "absolute", bottom: 20, left: 30, right: 30, textAlign: "center" }}
    render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`}
  />
</Page>
tsx
<Page size="A4">
  <View fixed style={{ position: "absolute", top: 20, left: 30, right: 30 }}>
    <Text>Header</Text>
  </View>
  <View style={{ marginTop: 60, marginBottom: 60 }}>
    <Text>Content</Text>
  </View>
  <Text
    fixed
    style={{ position: "absolute", bottom: 20, left: 30, right: 30, textAlign: "center" }}
    render={({ pageNumber, totalPages }) => `Page ${pageNumber} of ${totalPages}`}
  />
</Page>

Page Breaks and Wrapping

分页与内容包裹

tsx
<View break />                              // Force page break
<View wrap={false}><Text>Keep together</Text></View>  // Prevent breaking inside
<Text orphans={2} widows={2}>Long text...</Text>       // Orphan/widow control
<View minPresenceAhead={100}><Text>Content</Text></View>  // Min space before break
tsx
<View break />                              // 强制分页
<View wrap={false}><Text>Keep together</Text></View>  // 禁止内部拆分
<Text orphans={2} widows={2}>Long text...</Text>       // 孤行/ widow 控制
<View minPresenceAhead={100}><Text>Content</Text></View>  // 分页前最小预留空间

Custom Fonts

自定义字体

CRITICAL: All font sources MUST be local file paths. Remote URLs do not work.
tsx
import { Font } from "@react-pdf/renderer";

Font.register({
  family: "Roboto",
  fonts: [
    { src: "./fonts/Roboto-Regular.ttf", fontWeight: "normal" },
    { src: "./fonts/Roboto-Bold.ttf", fontWeight: "bold" },
    { src: "./fonts/Roboto-Italic.ttf", fontStyle: "italic" },
  ],
});

// Always disable hyphenation when using custom fonts
Font.registerHyphenationCallback((word) => [word]);
Built-in fonts: Courier, Helvetica, Times-Roman (each with Bold, Italic/Oblique variants)
Font weight values: thin (100), ultralight (200), light (300), normal (400), medium (500), semibold (600), bold (700), ultrabold (800), heavy (900)
关键提示:所有字体源必须是本地文件路径。远程URL无法使用。
tsx
import { Font } from "@react-pdf/renderer";

Font.register({
  family: "Roboto",
  fonts: [
    { src: "./fonts/Roboto-Regular.ttf", fontWeight: "normal" },
    { src: "./fonts/Roboto-Bold.ttf", fontWeight: "bold" },
    { src: "./fonts/Roboto-Italic.ttf", fontStyle: "italic" },
  ],
});

// 使用自定义字体时务必禁用断字功能
Font.registerHyphenationCallback((word) => [word]);
内置字体:Courier、Helvetica、Times-Roman(每种都有Bold、Italic/Oblique变体)
字体字重值:thin(100)、ultralight(200)、light(300)、normal(400)、medium(500)、semibold(600)、bold(700)、ultrabold(800)、heavy(900)

Google Fonts

Google Fonts

Use
references/google-fonts.txt
to find font URLs, then download locally:
bash
undefined
使用
references/google-fonts.txt
查找字体URL,然后下载到本地:
bash
undefined

Find the font URL

查找字体URL

grep "^Roboto" skills/react-pdf/references/google-fonts.txt | grep "700" | grep "normal"
grep "^Roboto" skills/react-pdf/references/google-fonts.txt | grep "700" | grep "normal"

Download

下载

mkdir -p fonts curl -sL "<url-from-grep>" -o fonts/Roboto-Bold.ttf
mkdir -p fonts curl -sL "<url-from-grep>" -o fonts/Roboto-Bold.ttf

Verify - must show "TrueType Font data"

验证 - 必须显示"TrueType Font data"

file fonts/Roboto-Bold.ttf

If `file` shows "HTML document" or "ASCII text", the download failed. Try a different URL or search
GitHub for the font's official repo with TTF files.
file fonts/Roboto-Bold.ttf

如果`file`命令显示“HTML document”或“ASCII text”,则下载失败。请尝试其他URL或在GitHub上搜索该字体的官方仓库以获取TTF文件。

Emoji

表情符号

Emoji won't render in PDFs unless you register an emoji source. Install
twemoji-emojis
to get local Twemoji PNG assets — no internet needed at render time.
bash
npm install twemoji-emojis
tsx
import { Font } from "@react-pdf/renderer";

Font.registerEmojiSource({
  format: "png",
  url: "node_modules/twemoji-emojis/vendor/72x72/",
});
Then use emoji directly in Text:
<Text>Hello 🚀🎉</Text>
除非注册表情符号源,否则表情符号无法在PDF中渲染。安装
twemoji-emojis
以获取本地Twemoji PNG资源 — 渲染时无需联网。
bash
npm install twemoji-emojis
tsx
import { Font } from "@react-pdf/renderer";

Font.registerEmojiSource({
  format: "png",
  url: "node_modules/twemoji-emojis/vendor/72x72/",
});
然后可在Text组件中直接使用表情符号:
<Text>Hello 🚀🎉</Text>

Other Features

其他功能

tsx
// Canvas drawing
<Canvas style={{ width: 200, height: 200 }}
  paint={(painter, w, h) => { painter.circle(w/2, h/2, 50).fill("#3498db"); }} />

// Annotation notes
<Note style={{ color: "yellow" }}>Annotation text</Note>

// Hyphenation
Font.registerHyphenationCallback((word) => [word]); // disable

// Debug mode - visualize boundaries
<View debug><Text debug>Debug text</Text></View>

// Document metadata
<Document title="My Doc" author="Author" subject="Report" language="en-US" pdfVersion="1.5" />
tsx
// Canvas绘制
<Canvas style={{ width: 200, height: 200 }}
  paint={(painter, w, h) => { painter.circle(w/2, h/2, 50).fill("#3498db"); }} />

// 注释笔记
<Note style={{ color: "yellow" }}>Annotation text</Note>

// 断字功能
Font.registerHyphenationCallback((word) => [word]); // 禁用

// 调试模式 - 可视化边界
<View debug><Text debug>Debug text</Text></View>

// 文档元数据
<Document title="My Doc" author="Author" subject="Report" language="en-US" pdfVersion="1.5" />

Best Practices

最佳实践

  1. Use
    StyleSheet.create()
    — define styles once and reuse
  2. Compress images before embedding, use
    cache={true}
    for remote images
  3. Test page breaks — content may flow differently than expected
  4. Prefer flexbox over absolute positioning
  5. Use
    fixed
    prop for headers/footers on every page
  6. Use
    debug={true}
    to visualize element boundaries
  7. Wrap rendering in try-catch blocks
  1. 使用
    StyleSheet.create()
    — 定义一次样式并复用
  2. 嵌入前压缩图片,对远程图片使用
    cache={true}
  3. 测试分页 — 内容的流动可能与预期不同
  4. 优先使用flexbox而非绝对定位
  5. 对每页的页眉/页脚使用
    fixed
    属性
  6. 使用
    debug={true}
    可视化元素边界
  7. 将渲染代码包裹在try-catch块中

Common Issues

常见问题

Text overflow:
<Text style={{ width: 200, maxLines: 3, textOverflow: "ellipsis" }}>...</Text>
Missing fonts: Download locally and register with local file paths. Remote URLs will NOT work.
Unexpected page breaks: Use
wrap={false}
to keep content together, or
<View break />
to force breaks.
文本溢出
<Text style={{ width: 200, maxLines: 3, textOverflow: "ellipsis" }}>...</Text>
字体缺失:下载到本地并使用本地文件路径注册。远程URL绝对无法使用。
意外分页:使用
wrap={false}
保持内容连续,或使用
<View break />
强制分页。