HTML要素やページの一部のセクションをC#でPDFに変換する方法

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPDFには、特定のHTML要素を対象とする組み込みのSelectCssメソッドは用意されていません。 ChromePdfRenderer は、完全な HTML ドキュメント(ページ全体、URL 全体、HTML 文字列全体)をレンダリングします。 ページの特定のセクションからPDFを生成するために、JavaScript DOM操作、CSSインジェクション、サーバーサイドのHTMLフラグメント抽出、URLレンダリングとJSターゲティングの4つのアプローチの1つを使用してレンダリング前にターゲット要素を分離します。

各アプローチは異なる制約に適しています。 JavaScript DOMの分離は、ターゲットを除いて全てを削除する必要がある場合に、URLや完全なページをレンダリングする際に機能します。 CSSインジェクションは、DOMを変更せずに不要なコンテンツを隠します。 サーバーサイドの抽出は、生のHTMLにアクセスできる場合に最もクリーンな結果を提供します。 URLレンダリングとJSターゲティングは、ソースHTMLが利用できないライブダッシュボードやサードパーティーページを処理します。

無料の30日間トライアルを開始して、全てのアプローチをテストしてください。

クイックスタート: 特定のHTML要素をPDFとして抽出

JavaScriptのDOM分離とWaitForを使用してCSSセレクタで任意の要素を指定し、その部分のみをPDFとしてレンダリングします。

  1. IronPDF をNuGetパッケージマネージャでインストール

    PM > Install-Package IronPdf
  2. このコード スニペットをコピーして実行します。

    using IronPdf;
    
    var renderer = new ChromePdfRenderer();
    renderer.RenderingOptions.EnableJavaScript = true;
    renderer.RenderingOptions.JavaScript = @"
        var target = document.querySelector('#invoice-summary');
        document.body.innerHTML = target.outerHTML;
    ";
    renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000);
    
    var pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
    pdf.SaveAs("invoice-summary.pdf");
  3. 実際の環境でテストするためにデプロイする

    今日プロジェクトで IronPDF を使い始めましょう無料トライアル

    arrow pointer

最小のワークフロー (3つのステップ)

  1. NuGet 経由で IronPdf をインストールします: Install-Package IronPdf
  2. ChromePdfRenderOptions.JavaScript を設定して対象要素を特定し、WaitFor を設定してその存在を確認します
  3. RenderHtmlAsPdf() または RenderUrlAsPdf() を呼び出してください — PDFには切り出されたコンテンツのみが含まれています

JavaScript DOM操作で要素を分離する方法は?

ChromePdfRenderOptions.JavaScript プロパティは、HTMLの読み込み完了後、PDFのレンダリング開始前に実行されるJavaScriptの文字列を受け付けます。 document.body.innerHTML をターゲット要素の outerHTML に置き換えることで、レンダリングされたページからそれ以外の要素をすべて除去します。 これは最も汎用性の高いアプローチであり、RenderUrlAsPdf()の両方で機能します。

WaitFor.HtmlQuerySelector() メソッドは、JavaScriptが実行される前に、対象の要素がDOM内に存在することを確認します。 これは非同期コンテンツを含むページでは重要です — Reactコンポーネント、Angularテンプレート、API駆動のデータが初期ページ読み込み後に入力されます。

using IronPdf;

string fullPageHtml = @"
<html>
<body>
    <header><h1>Acme Corp Invoice</h1></header>
    <nav>Navigation links...</nav>
    <div id='invoice-summary'>
        <h2>Invoice #12345</h2>
        <table>
            <tr><td>Widget A</td><td>$49.99</td></tr>
            <tr><td>Widget B</td><td>$29.99</td></tr>
            <tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
        </table>
    </div>
    <footer>Footer content...</footer>
</body>
</html>";

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;

// Replace the body with only the target element
renderer.RenderingOptions.JavaScript = @"
    var el = document.querySelector('#invoice-summary');
    if (el) {
        document.body.innerHTML = el.outerHTML;
    }
";

// Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-summary-only.pdf");
using IronPdf;

string fullPageHtml = @"
<html>
<body>
    <header><h1>Acme Corp Invoice</h1></header>
    <nav>Navigation links...</nav>
    <div id='invoice-summary'>
        <h2>Invoice #12345</h2>
        <table>
            <tr><td>Widget A</td><td>$49.99</td></tr>
            <tr><td>Widget B</td><td>$29.99</td></tr>
            <tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
        </table>
    </div>
    <footer>Footer content...</footer>
</body>
</html>";

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;

// Replace the body with only the target element
renderer.RenderingOptions.JavaScript = @"
    var el = document.querySelector('#invoice-summary');
    if (el) {
        document.body.innerHTML = el.outerHTML;
    }
";

// Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-summary-only.pdf");
Imports IronPdf

Dim fullPageHtml As String = "
<html>
<body>
    <header><h1>Acme Corp Invoice</h1></header>
    <nav>Navigation links...</nav>
    <div id='invoice-summary'>
        <h2>Invoice #12345</h2>
        <table>
            <tr><td>Widget A</td><td>$49.99</td></tr>
            <tr><td>Widget B</td><td>$29.99</td></tr>
            <tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
        </table>
    </div>
    <footer>Footer content...</footer>
</body>
</html>"

Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True

' Replace the body with only the target element
renderer.RenderingOptions.JavaScript = "
    var el = document.querySelector('#invoice-summary');
    if (el) {
        document.body.innerHTML = el.outerHTML;
    }
"

' Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000)

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fullPageHtml)
pdf.SaveAs("invoice-summary-only.pdf")
$vbLabelText   $csharpLabel

この JavaScript は、本文全体を #invoice-summary div の outerHTML に置き換えます。 結果のPDFには請求書テーブルのみが含まれます — ヘッダー、ナビゲーション、フッターはありません。 IDを指定してターゲットとする場合WaitFor.HtmlElementById()メソッドはよりシンプルな代替手段となります:

// Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000);
// Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000);
' Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000)
$vbLabelText   $csharpLabel

複雑なセレクタ(クラス名、データ属性、ネストされた要素)については、HtmlQuerySelector() は、document.querySelector() が受け入れる有効な CSS セレクタ文字列であれば、どのようなものでも受け入れます。 その他の WaitFor 便利メソッドには、HtmlElementByName()、および HtmlElementByTagName() などがあります。これらはそれぞれ内部で HtmlQuerySelector() に委譲されますが、コード内の意図をより明確に示します。

ターゲット要素が親コンテナから継承されたスタイルに依存している場合、outerHTMLによる置換により、祖先セレクタ(例:.dashboard .widget table { ...)に依存するCSSルールが失われる可能性があります。 })。 これらを維持するために、<head> 内の関連する <style> および <link> タグを JS 隔離領域にコピーしてください:

renderer.RenderingOptions.JavaScript = @"
    var el = document.querySelector('#invoice-summary');
    if (el) {
        var head = document.head.innerHTML;
        document.body.innerHTML = el.outerHTML;
        document.head.innerHTML = head;
    }
";
renderer.RenderingOptions.JavaScript = @"
    var el = document.querySelector('#invoice-summary');
    if (el) {
        var head = document.head.innerHTML;
        document.body.innerHTML = el.outerHTML;
        document.head.innerHTML = head;
    }
";
renderer.RenderingOptions.JavaScript = "
    var el = document.querySelector('#invoice-summary');
    if (el) {
        var head = document.head.innerHTML;
        document.body.innerHTML = el.outerHTML;
        document.head.innerHTML = head;
    }
"
$vbLabelText   $csharpLabel

これにより、元の <head> コンテンツ(スタイルシート、フォント、メタタグ)は保持されたまま、本文のみが置き換えられます。 "JavaScriptからPDFへの変換"および"WaitFor"のハウツー記事では、複数の非同期データソースを持つページ向けのNetworkIdle0()を含む、追加の設定オプションについて解説しています。

CSSインジェクションで要素を分離する方法は?

ChromePdfRenderOptions.CustomCssUrl プロパティは、IronPDF がレンダリング前に適用するスタイルシートのファイルパスまたは URL を受け付けます。 DOMを操作する代わりに、CSS display: none を使用して、対象要素以外のすべてを非表示にします。 これにより、元のDOM構造が保持され、JavaScriptの実行を完全に避けることができます。

using IronPdf;

// Create a CSS file that hides everything except #invoice-summary
string cssContent = @"
body > *:not(#invoice-summary) {
    display: none !important;
}
#invoice-summary {
    display: block !important;
    margin: 0;
    padding: 20px;
}
";
File.WriteAllText("isolate-element.css", cssContent);

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css";

PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-css-isolated.pdf");
using IronPdf;

// Create a CSS file that hides everything except #invoice-summary
string cssContent = @"
body > *:not(#invoice-summary) {
    display: none !important;
}
#invoice-summary {
    display: block !important;
    margin: 0;
    padding: 20px;
}
";
File.WriteAllText("isolate-element.css", cssContent);

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css";

PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-css-isolated.pdf");
Imports IronPdf
Imports System.IO

' Create a CSS file that hides everything except #invoice-summary
Dim cssContent As String = "
body > *:not(#invoice-summary) {
    display: none !important;
}
#invoice-summary {
    display: block !important;
    margin: 0;
    padding: 20px;
}
"
File.WriteAllText("isolate-element.css", cssContent)

Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css"

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fullPageHtml)
pdf.SaveAs("invoice-css-isolated.pdf")
$vbLabelText   $csharpLabel

注:CustomCssUrl プロパティは、HTML 文字列からレンダリングする場合にのみ RenderHtmlAsPdf() と連携して機能します。 URLのレンダリングについては、代わりにCSSインジェクションをJavaScriptプロパティに埋め込んでください:

renderer.RenderingOptions.JavaScript = @"
    var style = document.createElement('style');
    style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
    document.head.appendChild(style);
";
renderer.RenderingOptions.JavaScript = @"
    var style = document.createElement('style');
    style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
    document.head.appendChild(style);
";
renderer.RenderingOptions.JavaScript = "
    var style = document.createElement('style');
    style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
    document.head.appendChild(style);
"
$vbLabelText   $csharpLabel

ソースHTMLを制御できる場合、@media printルールが最も軽量な選択肢となります。外部依存関係がなく、ランタイムインジェクションも不要です:

@media print {
    header, nav, footer, .sidebar { display: none !important; }
    #invoice-summary { width: 100%; margin: 0; }
}

レンダラーで CssMediaType PdfCssMediaType.Print に設定して、これらのルールを有効にしてください:

renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print
$vbLabelText   $csharpLabel

これは、アプリケーション側ですでに @media print ルールが定義されているフォームセクションの PRINT シナリオ、またはフォームの HTML がサーバーサイドで組み立てられる"アプローチ 3"に最適です。

CSSのアプローチには、1つの重要な制限があります。それは、display: noneが不適切な特異性レベルで使用された場合、非表示の要素が依然としてドキュメントフロー内のスペースを占有してしまうことです。 特定のブレークポイントで要素の表示が変更される可能性があるフレームワークのスタイル(Bootstrap、Tailwind)を上書きするには、常に !important を使用してください。 深くネストされたターゲットの場合、より正確なセレクタがコラテラルな隠れを回避します。

body > *:not(#target),
body > *:not(#target) ~ * {
    display: none !important;
}

サーバーサイドでHTMLフラグメントを抽出する方法は?

ファイル、データベース、CMS、またはHTTPレスポンスから生のHTMLにアクセスできる場合、最もクリーンなアプローチは、HTMLパーサーを使用してサーバー側で対象要素を抽出し、そのフラグメントをRenderHtmlAsPdf()に渡すことです。 JavaScriptもCSSインジェクションも実行時DOM操作もありません。

AngleSharpは、このパターンの標準的な.NET HTMLパーサーです。

using IronPdf;
using AngleSharp;
using AngleSharp.Html.Parser;

string fullPageHtml = @"
<html>
<head>
    <style>
        table { border-collapse: collapse; width: 100%; }
        td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
    </style>
</head>
<body>
    <header><h1>Dashboard</h1></header>
    <div id='revenue-widget'>
        <h3>Q4 Revenue</h3>
        <table>
            <tr><th>Month</th><th>Revenue</th></tr>
            <tr><td>October</td><td>$1.2M</td></tr>
            <tr><td>November</td><td>$1.5M</td></tr>
            <tr><td>December</td><td>$1.8M</td></tr>
        </table>
    </div>
    <div id='other-content'>Other widgets...</div>
</body>
</html>";

// Parse and extract the target element
var parser = new HtmlParser();
var document = parser.ParseDocument(fullPageHtml);
var targetElement = document.QuerySelector("#revenue-widget");

if (targetElement is null)
{
    Console.WriteLine("Target element not found.");
    return;
}

// Wrap the fragment in a minimal HTML document to preserve styles
string fragmentHtml = $@"
<html>
<head>
    <style>
        table {{ border-collapse: collapse; width: 100%; }}
        td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
    </style>
</head>
<body>
    {targetElement.OuterHtml}
</body>
</html>";

var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget.pdf");
using IronPdf;
using AngleSharp;
using AngleSharp.Html.Parser;

string fullPageHtml = @"
<html>
<head>
    <style>
        table { border-collapse: collapse; width: 100%; }
        td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
    </style>
</head>
<body>
    <header><h1>Dashboard</h1></header>
    <div id='revenue-widget'>
        <h3>Q4 Revenue</h3>
        <table>
            <tr><th>Month</th><th>Revenue</th></tr>
            <tr><td>October</td><td>$1.2M</td></tr>
            <tr><td>November</td><td>$1.5M</td></tr>
            <tr><td>December</td><td>$1.8M</td></tr>
        </table>
    </div>
    <div id='other-content'>Other widgets...</div>
</body>
</html>";

// Parse and extract the target element
var parser = new HtmlParser();
var document = parser.ParseDocument(fullPageHtml);
var targetElement = document.QuerySelector("#revenue-widget");

if (targetElement is null)
{
    Console.WriteLine("Target element not found.");
    return;
}

// Wrap the fragment in a minimal HTML document to preserve styles
string fragmentHtml = $@"
<html>
<head>
    <style>
        table {{ border-collapse: collapse; width: 100%; }}
        td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
    </style>
</head>
<body>
    {targetElement.OuterHtml}
</body>
</html>";

var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget.pdf");
Imports IronPdf
Imports AngleSharp
Imports AngleSharp.Html.Parser

Dim fullPageHtml As String = "
<html>
<head>
    <style>
        table { border-collapse: collapse; width: 100%; }
        td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
    </style>
</head>
<body>
    <header><h1>Dashboard</h1></header>
    <div id='revenue-widget'>
        <h3>Q4 Revenue</h3>
        <table>
            <tr><th>Month</th><th>Revenue</th></tr>
            <tr><td>October</td><td>$1.2M</td></tr>
            <tr><td>November</td><td>$1.5M</td></tr>
            <tr><td>December</td><td>$1.8M</td></tr>
        </table>
    </div>
    <div id='other-content'>Other widgets...</div>
</body>
</html>"

' Parse and extract the target element
Dim parser As New HtmlParser()
Dim document = parser.ParseDocument(fullPageHtml)
Dim targetElement = document.QuerySelector("#revenue-widget")

If targetElement Is Nothing Then
    Console.WriteLine("Target element not found.")
    Return
End If

' Wrap the fragment in a minimal HTML document to preserve styles
Dim fragmentHtml As String = $"
<html>
<head>
    <style>
        table {{ border-collapse: collapse; width: 100%; }}
        td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
    </style>
</head>
<body>
    {targetElement.OuterHtml}
</body>
</html>"

Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml)
pdf.SaveAs("revenue-widget.pdf")
$vbLabelText   $csharpLabel

重要な点は、抽出された断片を、関連する <style> または <link> タグを含む完全な HTML ドキュメントで囲むことです。 このラッパーがないと、インラインスタイルは正しくレンダリングされるが、外部スタイルシートと継承されたCSSルールは失われます。メールテンプレートプレビューのレンダリングでは、すでに文字列として保存されているテンプレートHTMLは、この抽出パターンによってピクセル単位で完璧な結果を得ることができます。

同様のパターンは、代替パーサーとしてHtmlAgilityPackで機能します。

using HtmlAgilityPack;
using IronPdf;

var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(fullPageHtml);

var targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']");
if (targetNode is null)
{
    Console.WriteLine("Target element not found.");
    return;
}

string fragmentHtml = $"<html><body>{targetNode.OuterHtml}</body></html>";

var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget-hap.pdf");
using HtmlAgilityPack;
using IronPdf;

var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(fullPageHtml);

var targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']");
if (targetNode is null)
{
    Console.WriteLine("Target element not found.");
    return;
}

string fragmentHtml = $"<html><body>{targetNode.OuterHtml}</body></html>";

var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget-hap.pdf");
Imports HtmlAgilityPack
Imports IronPdf

Dim htmlDoc As New HtmlDocument()
htmlDoc.LoadHtml(fullPageHtml)

Dim targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']")
If targetNode Is Nothing Then
    Console.WriteLine("Target element not found.")
    Return
End If

Dim fragmentHtml As String = $"<html><body>{targetNode.OuterHtml}</body></html>"

Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml)
pdf.SaveAs("revenue-widget-hap.pdf")
$vbLabelText   $csharpLabel
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml, @"C:\templates\assets\");
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml, @"C:\templates\assets\");
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml, "C:\templates\assets\")
$vbLabelText   $csharpLabel

AngleSharpとHtmlAgilityPackの選択は主に好みの問題です。 AngleSharpはCSSセレクタ(QuerySelector)を使用しており、これはフロントエンド開発者の思考モデルに沿ったものです。 HtmlAgilityPackはXPath (SelectSingleNode) を使用しており、XMLを多用する.NETコードベースではより馴染み深いものです。

メールテンプレートプレビューのレンダリング-送信前にHTMLメールテンプレートのPDFプレビューを生成-は純粋なアプローチ3シナリオです。 テンプレートHTMLは保存された文字列であり、外部リソース(画像、フォント)は既知のURLでホストされており、RenderHtmlAsPdf()パラメータによってすべての相対パスが解決されます。

HTMLに、ReactやVueアプリケーションが実行時に生成する<div id="app"></div>が含まれている場合、抽出されるフラグメントは空になります。 そのような場合は、アプローチ1または4を使用します。

ライブURLをレンダリングする際に要素をターゲットにする方法は?

ソースHTMLにアクセスできないライブURL(サードパーティのダッシュボード、外部レポート、ホスト型アプリケーションなど)については、ページ読み込み後に特定のセクションを抽出するためにWaitForを組み合わせて使用します。

これは、ダッシュボードウィジェットをエクスポートするシナリオです: BIツールがウェブページ上でチャートやテーブルをレンダリングし、単一のウィジェットを利害関係者配信用のPDFとしてエクスポートする必要があります。

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;

// Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000);

// Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = @"
    var widget = document.querySelector('[data-widget=""revenue-chart""]');
    if (widget) {
        // Preserve computed styles by cloning into a clean body
        document.body.innerHTML = '';
        document.body.appendChild(widget);
    }
";

PdfDocument pdf = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report");
pdf.SaveAs("revenue-chart-export.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;

// Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000);

// Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = @"
    var widget = document.querySelector('[data-widget=""revenue-chart""]');
    if (widget) {
        // Preserve computed styles by cloning into a clean body
        document.body.innerHTML = '';
        document.body.appendChild(widget);
    }
";

PdfDocument pdf = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report");
pdf.SaveAs("revenue-chart-export.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True

' Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000)

' Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = "
    var widget = document.querySelector('[data-widget=""revenue-chart""]);
    if (widget) {
        // Preserve computed styles by cloning into a clean body
        document.body.innerHTML = '';
        document.body.appendChild(widget);
    }
"

Dim pdf As PdfDocument = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report")
pdf.SaveAs("revenue-chart-export.pdf")
$vbLabelText   $csharpLabel

WaitFor.HtmlQuerySelector() 呼び出しは、JavaScript が実行される前にウィジェットが DOM に存在することを保証します。 15秒のタイムアウトは、ダッシュボードデータを入力するAPI呼び出しの遅さに対応しています。 JavaScriptはその後、ページを該当のウィジェットのみへと削減します。

複雑なCSS依存関係を持つページの場合、appendChildのアプローチ(ノードをコピーするのではなく移動させる)は、要素がCSSOM内での位置を保持するため、より多くの計算済みスタイルを維持できます。 アプローチ 1 の innerHTML 置換手法はより単純ですが、祖先セレクタに依存するスタイルが失われる可能性があります。

対象ページで認証が必要な場合は、RenderUrlAsPdf()を呼び出す前に、レンダラーでクッキーを設定してください:

renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
    { "session_id", "abc123" },
    { "auth_token", "bearer-xyz" }
};
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
    { "session_id", "abc123" },
    { "auth_token", "bearer-xyz" }
};
Imports System.Collections.Generic

renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
    {"session_id", "abc123"},
    {"auth_token", "bearer-xyz"}
}
$vbLabelText   $csharpLabel

WaitFor クラスは、HtmlQuerySelector() を超える追加の待機戦略を提供します。 NetworkIdle0() は、すべてのネットワークリクエストが完了し、未処理の接続がゼロになるまで待機します。これは、複数の API エンドポイントからデータを読み込むダッシュボードなどで役立ちます。 NetworkIdle2() は最大 2 つのアクティブな接続を許容し、これにより、永続的な WebSocket 接続やロングポーリングを使用するページを処理できます。 JavaScript() は、ページが window.ironpdf.notifyRender() を呼び出すのを待機します。これは、ターゲットページを制御しており、すべてのデータの読み込みとアニメーションが完了した後、レンダリングの準備が整ったことを明示的に通知できる場合に最も正確な選択肢です。

定期的なダッシュボードエクスポート(例:夜間のPDF生成を利害関係者メール配信用)では、タイムアウト例外をキャッチするリトライループにレンダリングをラップします。 maxWaitTimeを超過した場合、IronPDFは利用可能なコンテンツ(不完全な場合がある)のレンダリングを続行します。 タイムアウト時間を延長するか、NetworkIdle0()に切り替えることで、通常、低速なネットワーク環境での断続的な障害は解消されます。

4つのアプローチの比較

アプローチ 最適 ソースHTMLが必要 JS依存 複雑
JavaScript DOMアイソレーション 任意のソースからの一般的な要素抽出 なし はい Medium
CSSインジェクション DOMの変更なしにセクションを隠します; @media print レイアウト 一部(CustomCssUrlには RenderHtmlAsPdf が必要です) なし(URLのためにJSで注入しない限り) Low
サーバーサイドフラグメント抽出 CMSコンテンツ、保存されたテンプレート、メールプレビュー はい なし 低–中
JSターゲティングによるURLレンダリング ライブダッシュボード、サードパーティーページ、SPAウィジェット なし はい 中 –高

正しいアプローチの選択

決定は2つの要素に依存します: 生のHTMLにアクセスできるかどうかと、ターゲットコンテンツがJavaScriptでレンダリングを必要としているかどうか。

Invoice 行単位の抽出が最も一般的なユースケースです。 請求書のHTMLがサーバーサイドで生成される場合(Razorビュー、Handlebarsテンプレート、保存されたHTML文字列)、アプローチ3(サーバーサイド抽出)はランタイムオーバーヘッドゼロで最もクリーンな結果を提供します。 #line-items テーブルを抽出し、スタイル設定された HTML シェルで囲み、レンダリングしてください。

Dashboard ウィジェットのエクスポートには JavaScript の実行が必要です。これは、ウィジェットのコンテンツが、最初のページ読み込み後に API 呼び出しによって生成されるためです。 アプローチ1(JS DOMアイソレーション)は、ダッシュボードがローカルで実行されるか、認証の背後にある場合に処理します。 アプローチ4(JSターゲティングによるURLレンダリング)は、ダッシュボードがサードパーティのホストされたアプリケーションでURLしか持たない場合に必要です。

Form セクションの印刷 — ユーザーの確認やコンプライアンス上のアーカイブのために、複数ステップからなるフォームの特定のセクションを抽出すること — は、アプリケーションがすでに @media print ルールを定義している場合はアプローチ 2(CSS インジェクション)に、フォームの HTML がサーバーサイドで組み立てられる場合はアプローチ 3 に、自然に該当します。

Email テンプレートのプレビューレンダリング(送信前にHTMLメールテンプレートのPDFプレビューを生成すること)は、純粋なアプローチ3のシナリオです。 テンプレートHTMLは保存された文字列であり、外部リソース(画像、フォント)は既知のURLでホストされており、RenderHtmlAsPdf()パラメータによってすべての相対パスが解決されます。

複数のシナリオをサポートする必要があるアプリケーションでは、戦略パラメータを受け入れるサービスインターフェースの背後でレンダリングロジックをカプセル化します。

public enum ElementExtractionStrategy
{
    JavaScriptIsolation,
    CssInjection,
    ServerSideExtraction,
    UrlWithJsTargeting
}
public enum ElementExtractionStrategy
{
    JavaScriptIsolation,
    CssInjection,
    ServerSideExtraction,
    UrlWithJsTargeting
}
Public Enum ElementExtractionStrategy
    JavaScriptIsolation
    CssInjection
    ServerSideExtraction
    UrlWithJsTargeting
End Enum
$vbLabelText   $csharpLabel

これにより、レンダラー構成を重複させることなく、入力タイプに基づいて適切なアプローチを呼び出すコードが選択できます。

次のステップ

IronPDFでのHTML要素のアイソレーションはレンダリング時の課題であり、組み込みのAPI機能ではありません。 上記の4つのアプローチは全範囲をカバーしています - サーバーサイドテンプレート抽出(ゼロJS、最もクリーンな出力)からライブURLターゲティング(完全なJS実行、SPAと非同期コンテンツに対応)まで。 比較表は迅速な参照を提供し、実世界のシナリオは一般的なビジネス要件を適切な戦略にマップします。

プロダクション展開に関する追加の考慮事項がいくつかあります:

パフォーマンス: サーバーサイド抽出(アプローチ3)はJavaScriptの実行を完全にスキップするため最速です。 JavaScript ベースのアプローチ(1 および 4)では、ページの複雑さと WaitFor タイムアウトに比例したオーバーヘッドが発生します。 バッチ処理(例:500件の請求書PDFを生成する場合)では、Parallel.ForEach および複数の ChromePdfRenderer インスタンスを使用したサーバーサイドでの抽出が、最高のスループットを実現します。

デバッグ: PDF 出力が空白になる、またはコンテンツが欠落する場合は、EnableJavaScript = true を有効にし、WaitFor のタイムアウト時間を延長してください。 ターゲット要素が非同期データに依存する場合、RenderDelayよりも信頼性が高いです。 レンダリングオプションガイドは、レイアウトに影響を与えるビューポート幅とペーパーフィットの構成をカバーしています。

アプローチの組み合わせ: 戦略のミックスを防ぐものはありません。 複数のフラグメント(1つのソースからのヘッダー、別のソースからのデータテーブル、第三のソースからのチャートSVG)からコンポジットHTMLドキュメントを構築するためにサーバーサイド抽出を使用し、組み立てたドキュメントを単一のPDFとしてレンダリングすることができます。 RenderHtmlAsPdf(string Html, string BaseUrlOrPath) メソッドは、ベース URL から相対的なアセットパスを解決するため、異種混在のソースからドキュメントを簡単に作成できます。

高度な JavaScript 実行パターンについては"JavaScript to PDF"ハウツー、利用可能なすべての待機戦略については"WaitFor"のドキュメントChromePdfRenderOptions インターフェースの全機能については"レンダリングオプションガイド"、すぐに実行できるスニペットについては"カスタム JavaScript コード例"をご覧ください。

$999 からライセンスオプションをご覧くださいChromePdfRenderOptions API リファレンスおよび WaitFor API リファレンスには、すべてのプロパティとメソッドが記載されています。

よくある質問

C#でHTML要素をPDFに変換する主要なアプローチは何ですか?

JS分離、CSS隠し、サーバーサイド抽出、ライブURLターゲティングが主要なアプローチであり、すべてIronPDFを使用して実装できます。

HTMLからPDFへの変換でJSの分離はどのように機能しますか?

JS分離は、JavaScriptを実行してHTMLドキュメントを動的に操作し、それをPDFに変換します。IronPDFを使用して特定の要素のみがレンダリングされることを確保します。

PDF変換においてCSSの隠しはどのように使用されますか?

CSSの隠しは、PDFに現れてはならない要素を隠すためにCSSスタイルを使用します。IronPDFは、変換プロセス中にスタイルシートやスタイルルールを指定することでこれをサポートします。

IronPDFは特定のHTML要素をサーバーサイドで抽出してPDFを生成できますか?

はい、IronPDFは特定のHTML要素をサーバーサイドで抽出し、ウェブページのどの部分がPDFに変換されるかを正確に制御します。

HTMLからPDFへの変換におけるライブURLターゲティングの利点は何ですか?

ライブURLターゲティングにより、IronPDFはライブウェブページのURLから要素を直接PDFに変換し、ローカルHTMLファイルが不要なまま、最新のコンテンツをキャプチャします。

IronPDFを使用して、ウェブページのセクションのみをPDFに変換できますか?

はい、IronPDFはウェブページの特定のセクションや要素をPDFに変換する機能を提供しており、関連コンテンツに容易に焦点を当てることができます。

IronPDFは、HTMLからPDFへの変換中に動的コンテンツをどのように処理しますか?

IronPDFは変換中にJavaScriptを実行して動的コンテンツをレンダリングし、クライアントサイドのスクリプトに依存する要素がPDF内で正確に表現されることを確保します。

カーティス・チャウ
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。

準備はできましたか?
Nuget ダウンロード 19,014,616 | バージョン: 2026.5 just released
Still Scrolling Icon

まだスクロールしていますか?

すぐに証拠が欲しいですか? PM > Install-Package IronPdf
サンプルを実行するHTML が PDF に変換されるのを確認します。