NaN/NaN/NaN

HTML to PDF変換を実装したはずなのに、生成されたPDFに文字化け・レイアウト崩れ・改ページの乱れ・画像の欠落――こうした問題が後を絶ちません。原因の多くは「PDF生成エンジンの仕様とHTML/CSSの書き方のミスマッチ」にあります。

この記事では、FUNBREW PDF をはじめとするHTML to PDF変換ツールで遭遇する代表的な10の問題を取り上げ、原因と解決策をBefore/Afterのコード例とともに解説します。HTML to PDF変換の全体像を既に把握している方を対象にした実践的なガイドです。

問題1: 文字化け・日本語フォントが表示されない

症状

日本語テキストが「□□□□」(豆腐)になる、または意図しない文字に置き換わる。

原因

PDF生成サーバーに日本語フォントがインストールされていないか、CSSでフォントが正しく指定されていない。セルフホストのwkhtmltopdfやPuppeteer環境では特に頻発します。

解決策

Before(問題のあるコード)

body {
  font-family: sans-serif; /* 汎用指定のみ、日本語フォントが見つからない */
}

After(修正後)

body {
  font-family: 'Noto Sans JP', 'Hiragino Sans', 'Yu Gothic', 'Meiryo', sans-serif;
}

/* 等幅フォントも日本語対応を明示 */
code, pre {
  font-family: 'Noto Sans Mono', 'Source Code Pro', monospace;
}

IPAフォントを使いたい場合は @font-face でBase64埋め込みが確実です。

@font-face {
  font-family: 'IPAexGothic';
  src: url('data:font/truetype;base64,AAEAAAA...') format('truetype');
}

body {
  font-family: 'IPAexGothic', sans-serif;
}

Google Fontsを使う場合は、ネットワークアクセス可能なサーバーであれば次の方法が手軽です。

@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap');

body {
  font-family: 'Noto Sans JP', sans-serif;
}

FUNBREW PDFではNoto Sans JPがプリインストールされているため、日本語フォントの追加設定は不要です。他のツールとの詳細な比較はHTML to PDF API比較 2026年版をご覧ください。

FUNBREW PDF APIでの指定例

curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<style>body { font-family: \"Noto Sans JP\", sans-serif; }</style><p>日本語テキスト</p>",
    "options": { "format": "A4" }
  }' \
  --output output.pdf

問題2: CSSレイアウトが崩れる

症状

ブラウザで正常に表示されるHTMLが、PDFにするとカラムが縦並びになる・ボックスがはみ出す・フレックスレイアウトが崩れる。

原因

PDF生成エンジン(特にwkhtmltopdfなどWebKitベース)が最新のCSSに完全対応していない。また、ビューポート幅が想定と異なる場合も原因になります。

解決策

Before(問題になりやすいコード)

.container {
  display: flex;
  gap: 24px; /* gapプロパティは古いエンジンで未対応 */
}

.column {
  width: 50%; /* flexboxと組み合わせると挙動が不安定 */
}

After(PDF生成対応の書き方)

/* テーブルレイアウトで安定した2カラムを実現 */
.container {
  display: table;
  width: 100%;
  border-spacing: 0;
}

.column {
  display: table-cell;
  width: 50%;
  padding-right: 12px;
  vertical-align: top;
}

.column:last-child {
  padding-right: 0;
  padding-left: 12px;
}

Chromiumベースのエンジンを使う場合は、flexboxやgridを固定幅で使うことで安定します。

@media print {
  .container {
    display: flex;
    width: 794px; /* A4幅(96dpi)に固定 */
    margin: 0;
    padding: 0;
  }

  .column {
    flex: 0 0 50%;
    box-sizing: border-box;
  }
}

レスポンシブデザインをPDFに変換すると意図しないモバイルレイアウトになることがあります。

/* ビューポートをA4幅で固定 */
@media print {
  .container {
    max-width: none !important;
    width: 100% !important;
  }

  /* メディアクエリによるモバイル切り替えをリセット */
  .mobile-only {
    display: none !important;
  }

  .desktop-only {
    display: block !important;
  }
}

背景色が出力されない問題も多いです。

* {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

エンジン別のCSS対応の詳細はwkhtmltopdf vs Chromium比較で確認できます。


問題3: 改ページが意図しない位置で発生する

症状

テーブルの途中でページが切れる・見出しだけが前のページに残る・特定のセクションを新しいページから始めたい。

原因

break-insidebreak-before の指定が不足している、または古いエンジン向けのフォールバックが抜けている。

解決策

Before

/* 何も指定なし → エンジンが自動で改ページ位置を決定 */
table { width: 100%; }

After(改ページを制御する)

/* 要素の途中で切れるのを防ぐ */
table, figure, .card, .invoice-item {
  break-inside: avoid;
  page-break-inside: avoid; /* 古いエンジン向けフォールバック */
}

/* 見出しの後で改ページさせない */
h1, h2, h3 {
  break-after: avoid;
  page-break-after: avoid;
}

/* セクションを必ず新ページから始める */
.chapter, .page-break {
  break-before: page;
  page-break-before: always;
}

/* 孤立行・寡婦行の防止 */
p {
  orphans: 3;  /* ページ下部に残る最小行数 */
  widows: 3;   /* ページ上部に来る最小行数 */
}

テーブルが複数ページにまたがる場合のヘッダー繰り返しも重要です。

/* ページをまたぐテーブルでヘッダーを繰り返す */
thead {
  display: table-header-group;
}

tfoot {
  display: table-footer-group;
}

/* 行の途中切れを防ぐ */
tr {
  break-inside: avoid;
  page-break-inside: avoid;
}

請求書のような構造では、合計行を必ず同じページに収める工夫が必要です。

<div class="invoice-body">
  <table class="line-items">
    <thead>
      <tr><th>品目</th><th>数量</th><th>単価</th><th>金額</th></tr>
    </thead>
    <tbody>
      <!-- 明細行 -->
    </tbody>
  </table>
</div>

<!-- 合計・振込先は改ページさせない -->
<div class="invoice-summary" style="break-inside: avoid; page-break-inside: avoid;">
  <table>
    <tr><td>小計</td><td>¥100,000</td></tr>
    <tr><td>消費税(10%)</td><td>¥10,000</td></tr>
    <tr><td><strong>合計</strong></td><td><strong>¥110,000</strong></td></tr>
  </table>
  <p>振込先: サンプル銀行 渋谷支店 普通 1234567</p>
</div>

CSSによる改ページ制御の詳細はHTML to PDF CSS最適化ガイドを参照してください。


問題4: 画像が表示されない

症状

HTMLの画像がPDFで空白になる・赤い×印になる・別の画像に化ける。

原因

相対URLを使っている・PDF生成サーバーからリソースへのアクセスができない・ローカルファイルパスを参照している。

解決策

Before(ローカル相対パスや相対URL)

<!-- ローカルファイル: PDF生成サーバーからアクセス不可 -->
<img src="../images/logo.png" alt="ロゴ">

<!-- 相対URL: サーバーのベースURLが不明 -->
<img src="/images/logo.png" alt="ロゴ">

After(絶対URL)

<!-- 絶対URLを使う -->
<img src="https://example.com/images/logo.png" alt="ロゴ">

外部にアクセスできない環境や、ネットワーク遅延を避けたい場合はBase64でインライン埋め込みします。

import base64

def image_to_base64(path: str) -> str:
    with open(path, 'rb') as f:
        return base64.b64encode(f.read()).decode('utf-8')

logo_b64 = image_to_base64('logo.png')

html = f'''
<img src="data:image/png;base64,{logo_b64}" alt="ロゴ" width="200">
'''

Node.jsの場合。

const fs = require('fs');

function imageToBase64(path) {
  const data = fs.readFileSync(path);
  return data.toString('base64');
}

const logoB64 = imageToBase64('./logo.png');
const html = `<img src="data:image/png;base64,${logoB64}" alt="ロゴ" width="200">`;

SVGもBase64でインライン埋め込みできます。直接 <svg> タグをHTMLに埋め込む方法も有効です。

<!-- SVGを直接埋め込む -->
<svg width="200" height="60" xmlns="http://www.w3.org/2000/svg">
  <text x="10" y="40" font-size="32" font-family="Noto Sans JP">FUNBREW</text>
</svg>

FUNBREW PDF APIでの画像指定

curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<img src=\"https://your-cdn.example.com/logo.png\" alt=\"ロゴ\"><p>本文</p>",
    "options": { "format": "A4" }
  }' \
  --output output.pdf

問題5: テーブルが見切れる・横スクロールが効かない

症状

列数の多いテーブルがページ幅を超えてはみ出す・テーブルの右端が切れてPDFに収まらない。

原因

PDFは横スクロールという概念がないため、overflow: auto が無効になる。テーブルがページ幅より広い場合、単純に切り取られます。

解決策

Before(ブラウザではスクロールで見えるが、PDFでは切れる)

.table-wrapper {
  overflow-x: auto; /* PDFでは無効 */
}

table {
  min-width: 900px; /* A4幅(約794px)を超えている */
}

After(PDFに収まるよう調整)

table {
  width: 100%;
  table-layout: fixed; /* 列幅を均等に分配 */
  word-break: break-all; /* 長いテキストを折り返す */
}

/* 列数が多い場合はフォントサイズを下げる */
@media print {
  table {
    font-size: 8pt;
  }

  td, th {
    padding: 4px 6px;
  }
}

/* 横向き用紙を使う */
@page {
  size: A4 landscape;
}

列数が非常に多い場合は用紙を横向きにする方が現実的です。

# FUNBREW PDF APIで横向きPDF生成
curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<table>...</table>",
    "options": {
      "format": "A4",
      "landscape": true
    }
  }' \
  --output output.pdf

不要な列を印刷時に非表示にする方法も効果的です。

/* 補足情報の列をPDFでは非表示 */
@media print {
  .col-notes,
  .col-actions {
    display: none;
  }
}

問題6: フォントや装飾が反映されない・スタイルが崩れる

症状

太字・斜体・下線などのスタイルが反映されない・外部CSSファイルが読み込まれない・特定のCSSプロパティが無視される。

原因

外部CSSファイルへの参照が相対URLになっている・PDF生成サーバーから外部リソースに到達できない・エンジンがCSSプロパティをサポートしていない。

解決策

Before(外部CSSファイルの参照)

<link rel="stylesheet" href="/assets/style.css"> <!-- PDF生成サーバーからアクセス不可の場合がある -->

After(CSSをインラインに埋め込む)

<style>
  /* CSSをすべてstyleタグ内に記述する */
  body {
    font-family: 'Noto Sans JP', sans-serif;
    font-size: 11pt;
    line-height: 1.7;
    color: #1a202c;
    margin: 0;
    padding: 0;
  }

  h1 { font-size: 18pt; font-weight: 700; margin-bottom: 12pt; }
  h2 { font-size: 14pt; font-weight: 700; margin-bottom: 8pt; }

  .highlight { background: #fef9c3; padding: 2px 4px; }
</style>

サーバーサイドでCSSファイルを読み込んでインライン化するのがベストプラクティスです。

# Python: CSSをHTMLに埋め込んでからAPIに送る
def build_html_with_styles(html_content: str, css_path: str) -> str:
    with open(css_path, 'r', encoding='utf-8') as f:
        css = f.read()
    return f'<style>{css}</style>{html_content}'

html = build_html_with_styles('<h1>レポート</h1>', 'style.css')
// Node.js: CSSをHTMLに埋め込む
const fs = require('fs');

function buildHtmlWithStyles(htmlContent, cssPath) {
  const css = fs.readFileSync(cssPath, 'utf-8');
  return `<style>${css}</style>${htmlContent}`;
}

const html = buildHtmlWithStyles('<h1>レポート</h1>', './style.css');

問題7: レンダリング待機不足による欠落(JavaScriptコンテンツ)

症状

グラフ・チャート・動的に生成されるコンテンツがPDFに反映されない・空白のキャンバスが表示される。

原因

PDF生成エンジンがJavaScriptの実行完了を待たずにPDFを生成している。

解決策

Before(JavaScriptが完了する前にPDF生成)

{
  "html": "<canvas id='chart'></canvas><script>renderChart();</script>",
  "options": {}
}

After(レンダリング完了を待つ)

// PDF生成前にJavaScriptの実行を待機させるシグナルを使う
const html = `
<canvas id="chart"></canvas>
<script>
  async function main() {
    await renderChart(); // チャートのレンダリングを完了させる
    // 完了シグナルを送る(PDF生成エンジンが認識)
    document.title = 'pdf-ready';
  }
  main();
</script>
`;

チャートライブラリ(Chart.js等)ではアニメーションを無効にするのが鉄則です。

// Chart.jsのアニメーションを無効化
const chart = new Chart(ctx, {
  type: 'bar',
  data: { ... },
  options: {
    animation: false,  // アニメーションを無効化
    responsive: false, // レスポンシブも無効化(固定サイズに)
    plugins: {
      legend: { display: true }
    }
  }
});

静的なSVGやサーバーサイドで生成した画像を使う方法が最も確実です。

# サーバーサイドでMatplotlibを使ってグラフをBase64画像に変換
import matplotlib.pyplot as plt
import io, base64

def chart_to_base64(data: list) -> str:
    fig, ax = plt.subplots(figsize=(6, 4))
    ax.bar(range(len(data)), data)
    buf = io.BytesIO()
    fig.savefig(buf, format='png', dpi=150, bbox_inches='tight')
    buf.seek(0)
    return base64.b64encode(buf.read()).decode()

chart_b64 = chart_to_base64([10, 25, 40, 35, 55])
html = f'<img src="data:image/png;base64,{chart_b64}" alt="売上グラフ">'

問題8: ヘッダー・フッターが表示されない

症状

@page のマージンを設定してヘッダー・フッター要素を配置したが、PDFでは重なる・切れる・表示されない。

原因

ヘッダー・フッターの描画方法はPDFエンジンによって異なります。CSS @page のマージンボックス(@top-center@bottom-center)をサポートしないエンジンが多く、CSS単体のアプローチでは失敗しがちです。

解決策

Before(多くのエンジンで動作しないCSS単体のヘッダー)

@page {
  @top-center { content: "会社名"; }
  @bottom-right { content: "Page " counter(page); }
}

After(position: fixedで確実に表示するパターン)

<style>
  @page {
    margin: 25mm 15mm 25mm 15mm; /* ヘッダー・フッター用の余白を確保 */
  }

  .page-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 15mm;
    text-align: center;
    font-size: 9pt;
    color: #718096;
    border-bottom: 0.5pt solid #e2e8f0;
    padding-bottom: 2mm;
  }

  .page-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 15mm;
    text-align: center;
    font-size: 8pt;
    color: #a0aec0;
  }
</style>

<div class="page-header">株式会社サンプル — 社外秘</div>
<div class="page-footer">FUNBREW PDF で生成</div>
<div class="content">
  <!-- メインコンテンツ -->
</div>

ページ番号を入れたい場合は、FUNBREW PDF APIのヘッダー・フッターオプションを使うのが確実です。

curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>レポート</h1><p>本文...</p>",
    "options": {
      "format": "A4",
      "margin": { "top": "25mm", "bottom": "25mm" },
      "displayHeaderFooter": true,
      "headerTemplate": "<div style=\"font-size:9px; text-align:center; width:100%;\">社外秘レポート</div>",
      "footerTemplate": "<div style=\"font-size:9px; text-align:center; width:100%;\"><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span> ページ</div>"
    }
  }' \
  --output output.pdf

問題9: PDF生成がタイムアウト・遅い

症状

APIリクエストが30秒以上かかりタイムアウトする。単純なページなのに生成が遅い。

原因

大きな画像の埋め込み、外部リソースの読み込み(フォント・CSS・画像がCDNから遅い)、複雑なJavaScript実行、またはHTMLペイロードが巨大。

解決策

画像を埋め込む前にリサイズ・圧縮する

from PIL import Image
import io, base64

def optimize_image(path: str, max_width: int = 800, quality: int = 80) -> str:
    """Base64埋め込み前に画像をリサイズ・圧縮する"""
    img = Image.open(path)
    if img.width > max_width:
        ratio = max_width / img.width
        img = img.resize((max_width, int(img.height * ratio)), Image.LANCZOS)
    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=quality, optimize=True)
    return base64.b64encode(buf.getvalue()).decode()

外部リソースをすべてインライン化する

import re, requests, base64

def inline_external_resources(html: str) -> str:
    """外部画像URLをBase64インラインデータに置換する"""
    def replace_src(match):
        url = match.group(1)
        if url.startswith("data:"):
            return match.group(0)
        try:
            resp = requests.get(url, timeout=10)
            content_type = resp.headers.get("content-type", "image/png")
            b64 = base64.b64encode(resp.content).decode()
            return f'src="data:{content_type};base64,{b64}"'
        except Exception:
            return match.group(0)

    return re.sub(r'src="(https?://[^"]+)"', replace_src, html)

タイムアウトの設定とペイロードサイズの削減

// HTMLの不要な空白を除去して軽量化
function compressHtml(html) {
  return html.replace(/\s+/g, ' ').replace(/>\s+</g, '><').trim();
}

const response = await axios.post(
  'https://pdf.funbrew.cloud/api/v1/generate',
  { html: compressHtml(html), options: { format: 'A4' } },
  { timeout: 60000 } // 余裕を持ったタイムアウトを設定
);

問題10: PDFファイルサイズが大きすぎる

症状

1ページのPDFが数MBになる。バッチ生成したPDFのストレージ消費が膨大。メール添付のサイズ上限を超える。

原因

高解像度の埋め込み画像(特に非圧縮PNG)、埋め込みフォント、冗長なCSSが原因。

解決策

画像を埋め込む前に圧縮する

写真にはPNG(非圧縮)ではなくJPEGを使い、ロゴやアイコンにはSVGを使います。

# 写真はJPEGで(PNGよりはるかに軽量)
img.save(buf, format="JPEG", quality=75, optimize=True)

# ロゴやシンプルなグラフィックはSVG(Base64不要)
logo_svg = '<svg width="200" height="60">...</svg>'

印刷向けに画像解像度を制限する

img {
  max-width: 100%;
  height: auto;
  image-rendering: optimizeQuality; /* エンジンにDPIスケーリングを任せる */
}

生成後のPDFを後処理で圧縮する

import subprocess

def compress_pdf(input_path: str, output_path: str):
    """Ghostscriptを使ってPDFファイルを圧縮する"""
    subprocess.run([
        "gs", "-sDEVICE=pdfwrite",
        "-dCompatibilityLevel=1.4",
        "-dPDFSETTINGS=/ebook",  # 品質とサイズのバランスが良い
        "-dNOPAUSE", "-dBATCH",
        f"-sOutputFile={output_path}",
        input_path,
    ], check=True)

# /screen  = 72 dpi(最小、低品質)
# /ebook   = 150 dpi(バランス型)
# /printer = 300 dpi(高品質)
# /prepress = 300 dpi(最高品質)
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);

async function compressPdf(inputPath, outputPath) {
  await execAsync(
    `gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH -sOutputFile=${outputPath} ${inputPath}`
  );
}

デバッグのコツ・トラブルシューティングフロー

問題を素早く特定するためのフローです。

ステップ1: ブラウザの印刷プレビューで確認

多くの問題はブラウザの印刷プレビューで再現します。

  1. ChromeでHTMLを開く
  2. Ctrl+Shift+P(Mac: Cmd+Shift+P)でコマンドパレットを開く
  3. "Emulate CSS media type" → "print" を選択
  4. Ctrl+P で印刷プレビューを確認

これで問題が再現すれば、CSS側の問題です。印刷プレビューで正常ならPDF生成エンジン固有の問題を疑います。

ステップ2: Playgroundでリアルタイムテスト

FUNBREW PDFのPlaygroundにHTMLを貼り付けると、APIキー不要でPDF出力を即座に確認できます。

ステップ3: エンジンを切り替えてテスト

FUNBREW PDFには fast(WebKitベース)と quality(Chromiumベース)の2エンジンがあります。

# fastエンジン(wkhtmltopdfベース、軽量)
curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<p>テスト</p>",
    "options": { "engine": "fast" }
  }' \
  --output test-fast.pdf

# qualityエンジン(Chromiumベース、高品質)
curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<p>テスト</p>",
    "options": { "engine": "quality" }
  }' \
  --output test-quality.pdf

2つのエンジンで出力が異なれば、CSS互換性の問題です。wkhtmltopdf vs Chromiumの詳細比較を参照してください。

ステップ4: 最小再現ケースを作る

複雑なHTMLから問題を特定するには、問題が再現する最小限のHTMLを作ることが近道です。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
  /* 問題のあるスタイルだけを記述 */
  body { font-family: 'Noto Sans JP', sans-serif; }
</style>
</head>
<body>
  <!-- 問題が再現する最小限のHTML要素 -->
  <p>テスト文字: あいうえお</p>
</body>
</html>

ステップ5: エラーレスポンスを確認する

import requests

response = requests.post(
    "https://pdf.funbrew.cloud/api/v1/pdf/generate",
    headers={"X-API-Key": "your-api-key"},
    json={"html": html_content, "options": {}},
)

if response.status_code != 200:
    # エラー詳細を確認
    print(f"HTTP {response.status_code}")
    print(response.json())  # エラーメッセージを確認
else:
    with open("output.pdf", "wb") as f:
        f.write(response.content)

エラーハンドリングの詳細はPDF APIエラーハンドリングガイドを参照してください。


問題と解決策のまとめ

問題 主な原因 解決策
文字化け(豆腐) 日本語フォント未インストール フォントスタック指定、プリインストールフォント使用
レイアウト崩れ CSS非互換、ビューポート問題 テーブルレイアウト使用、@media print で固定
意図しない改ページ break-inside 指定不足 break-inside: avoid + orphans/widows 指定
画像が表示されない 相対URL、アクセス不可 絶対URL使用、またはBase64埋め込み
テーブル見切れ 横幅超過 table-layout: fixed + word-break: break-all
スタイル反映なし 外部CSS未読み込み CSSをインライン化してAPIに送る
動的コンテンツ欠落 JS完了前にPDF生成 サーバーサイドでの静的画像変換
ヘッダー・フッター非表示 @page マージンルール非対応 position: fixed またはAPIのヘッダー・フッターオプション
生成遅い・タイムアウト 大きな画像、外部リソース 画像最適化、リソースインライン化、HTML圧縮
ファイルサイズ過大 非圧縮画像、埋め込みフォント JPEGでPNG代替、SVGアイコン、Ghostscript後処理

まとめ

HTML to PDF変換のトラブルは、ほとんどが「エンジンの仕様を知った上でHTMLとCSSを書く」ことで防げます。

  • 文字化け: 日本語フォントを明示的に指定する。FUNBREW PDFならNoto Sans JP標準対応
  • レイアウト崩れ: CSSをインライン化し、PDFエンジン対応の書き方にする
  • 改ページ: break-inside: avoidorphans/widows を組み合わせる
  • 画像・リソース: 絶対URLまたはBase64でインライン埋め込みする
  • ヘッダー・フッター: position: fixed またはAPIのヘッダー・フッターテンプレートオプションを使う
  • 生成が遅い: 画像を最適化・インライン化してからAPI送信、HTML空白を圧縮
  • ファイルサイズ: 写真はJPEG、グラフィックはSVG、必要に応じてGhostscriptで後処理
  • デバッグ: ブラウザ印刷プレビュー → Playgroundテスト → 最小再現ケースの順で絞り込む

各問題の詳細はHTML to PDF CSS最適化ガイドwkhtmltopdf vs Chromium比較で解説しています。まずはPlaygroundで実際に試しながら問題を確認することをおすすめします。

関連リンク

Powered by FUNBREW PDF