DEV Community

IronSoftware
IronSoftware

Posted on

PDF Table of Contents in C# (Developer Guide)

Long documents need navigation. A table of contents with clickable links lets readers jump directly to sections. Here's how to generate one automatically from your HTML headings.

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new [ChromePdfRenderer](https://ironpdf.com/blog/videos/how-to-render-html-string-to-pdf-in-csharp-ironpdf/)();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

var html = @"
<h1>Introduction</h1>
<p>Opening content...</p>
<h2>Background</h2>
<p>More content...</p>
<h1>Main Topic</h1>
<p>Details here...</p>";

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document-with-toc.pdf");
Enter fullscreen mode Exit fullscreen mode

IronPDF scans your HTML for heading tags (h1-h6) and generates a linked table of contents automatically.

How Does Automatic TOC Generation Work?

When you enable TableOfContents:

  1. IronPDF parses your HTML for <h1> through <h6> tags
  2. Extracts heading text and determines hierarchy
  3. Generates a TOC page with clickable hyperlinks
  4. Links jump directly to each heading in the PDF

The TOC appears at the beginning by default, or you can control placement with a placeholder div.

What Are the TOC Options?

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

// With hyperlinks (recommended)
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

// Plain text only (no navigation)
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.TextOnly;

// Disabled (default)
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.None;
Enter fullscreen mode Exit fullscreen mode

Use WithLinks for interactive PDFs. TextOnly for print-focused documents where links don't matter.

How Do I Control TOC Placement?

By default, TOC goes at the start. Place it elsewhere with a div:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

var html = @"
<html>
<body>
    <h1>Title Page</h1>
    <p>Welcome to this document.</p>

    <!-- TOC will be inserted here -->
    <div id='ironpdf-toc'></div>

    <h1>Chapter 1</h1>
    <p>First chapter content...</p>

    <h1>Chapter 2</h1>
    <p>Second chapter content...</p>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
Enter fullscreen mode Exit fullscreen mode

The id='ironpdf-toc' div marks where the TOC should appear.

How Do I Style the Table of Contents?

Custom CSS for TOC appearance:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

var html = @"
<html>
<head>
    <style>
        /* TOC container */
        .ironpdf-toc {
            padding: 20px;
            margin: 20px 0;
        }

        /* TOC title */
        .ironpdf-toc-title {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 15px;
            color: #333;
        }

        /* TOC entries */
        .ironpdf-toc-item {
            margin: 8px 0;
        }

        /* Indentation for nested headings */
        .ironpdf-toc-item-h1 { margin-left: 0; font-weight: bold; }
        .ironpdf-toc-item-h2 { margin-left: 20px; }
        .ironpdf-toc-item-h3 { margin-left: 40px; }
        .ironpdf-toc-item-h4 { margin-left: 60px; }

        /* Links */
        .ironpdf-toc-item a {
            color: #007bff;
            text-decoration: none;
        }

        .ironpdf-toc-item a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <div id='ironpdf-toc'></div>

    <h1>Introduction</h1>
    <h2>Purpose</h2>
    <h2>Scope</h2>
    <h1>Details</h1>
    <h2>Implementation</h2>
    <h3>Step 1</h3>
    <h3>Step 2</h3>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
Enter fullscreen mode Exit fullscreen mode

CSS selectors target TOC elements for full styling control.

How Do I Add Bookmarks Manually?

For existing PDFs or custom navigation:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("report.pdf");

// Add top-level bookmarks
pdf.Bookmarks.AddBookMarkAtEnd("Executive Summary", 0);
pdf.Bookmarks.AddBookMarkAtEnd("Introduction", 2);
pdf.Bookmarks.AddBookMarkAtEnd("Analysis", 5);
pdf.Bookmarks.AddBookMarkAtEnd("Conclusions", 15);
pdf.Bookmarks.AddBookMarkAtEnd("References", 18);

pdf.SaveAs("bookmarked-report.pdf");
Enter fullscreen mode Exit fullscreen mode

Bookmarks appear in the PDF reader's sidebar for navigation. Page numbers are zero-indexed.

How Do I Create Nested Bookmarks?

Hierarchical structure for complex documents:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("manual.pdf");

// Top-level sections
var chapter1 = pdf.Bookmarks.AddBookMarkAtEnd("Chapter 1: Getting Started", 0);
var chapter2 = pdf.Bookmarks.AddBookMarkAtEnd("Chapter 2: Advanced Topics", 10);
var chapter3 = pdf.Bookmarks.AddBookMarkAtEnd("Chapter 3: Reference", 25);

// Nested under Chapter 1
chapter1.Children.AddBookMarkAtEnd("1.1 Installation", 1);
chapter1.Children.AddBookMarkAtEnd("1.2 Configuration", 3);
chapter1.Children.AddBookMarkAtEnd("1.3 First Steps", 6);

// Nested under Chapter 2
chapter2.Children.AddBookMarkAtEnd("2.1 Performance", 11);
chapter2.Children.AddBookMarkAtEnd("2.2 Security", 15);
var section23 = chapter2.Children.AddBookMarkAtEnd("2.3 Integration", 18);

// Third level nesting
section23.Children.AddBookMarkAtEnd("2.3.1 API Setup", 19);
section23.Children.AddBookMarkAtEnd("2.3.2 Authentication", 21);

pdf.SaveAs("nested-bookmarks.pdf");
Enter fullscreen mode Exit fullscreen mode

Nested bookmarks create a tree structure in the PDF reader's navigation panel.

How Do I Read Existing Bookmarks?

Inspect and manipulate existing bookmarks:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var pdf = PdfDocument.FromFile("existing-document.pdf");

// Get all bookmarks
var bookmarks = pdf.Bookmarks.GetAllBookmarks();

foreach (var bookmark in bookmarks)
{
    Console.WriteLine($"Title: {bookmark.Title}, Page: {bookmark.PageIndex}");

    // Check for children
    foreach (var child in bookmark.Children)
    {
        Console.WriteLine($"  - {child.Title}, Page: {child.PageIndex}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Useful for auditing documents or building custom navigation interfaces.

How Do I Generate TOC for Merged Documents?

Important: Merge before adding TOC, not after:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

// Merge documents first
var part1 = PdfDocument.FromFile("chapter1.pdf");
var part2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(part1, part2);

// Then add bookmarks manually
merged.Bookmarks.AddBookMarkAtEnd("Chapter 1", 0);
merged.Bookmarks.AddBookMarkAtEnd("Chapter 2", part1.PageCount);

merged.SaveAs("complete-book.pdf");

// Note: Automatic TOC won't work after merge
// because heading tags are lost in the PDF
Enter fullscreen mode Exit fullscreen mode

For HTML-based TOC, generate from a single HTML document, not merged PDFs.

How Do I Create a TOC with Page Numbers?

Include page numbers in the TOC:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

var html = @"
<html>
<head>
    <style>
        .ironpdf-toc-item {
            display: flex;
            justify-content: space-between;
        }

        .ironpdf-toc-item-text {
            flex: 1;
        }

        .ironpdf-toc-item-page {
            margin-left: 10px;
        }

        /* Dotted leader line */
        .ironpdf-toc-item::after {
            content: '';
            flex: 1;
            border-bottom: 1px dotted #999;
            margin: 0 10px;
        }
    </style>
</head>
<body>
    <div id='ironpdf-toc'></div>

    <h1>Section 1</h1>
    <p>Content...</p>

    <h1>Section 2</h1>
    <p>More content...</p>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
Enter fullscreen mode Exit fullscreen mode

CSS styling creates the classic dotted-line leader between title and page number.

How Do I Handle Long Documents?

For documents with many sections:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

// Only include h1 and h2 in TOC to keep it manageable
var html = @"
<html>
<head>
    <style>
        /* Hide h3+ from TOC */
        .ironpdf-toc-item-h3,
        .ironpdf-toc-item-h4,
        .ironpdf-toc-item-h5,
        .ironpdf-toc-item-h6 {
            display: none;
        }
    </style>
</head>
<body>
    <div id='ironpdf-toc'></div>

    <h1>Part 1</h1>
    <h2>Chapter 1</h2>
    <h3>Section 1.1</h3>  <!-- Hidden from TOC -->
    <h3>Section 1.2</h3>  <!-- Hidden from TOC -->
    <h2>Chapter 2</h2>
</body>
</html>";

var pdf = renderer.RenderHtmlAsPdf(html);
Enter fullscreen mode Exit fullscreen mode

Limit TOC depth to keep navigation manageable.

How Do I Add Page Numbers to Headers?

Match TOC entries with visible page numbers:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TableOfContents = TableOfContentsTypes.WithLinks;

// Add page numbers in footer
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = @"
        <div style='text-align:center; font-size:10px;'>
            Page {page}
        </div>"
};

var pdf = renderer.RenderHtmlAsPdf(documentHtml);
Enter fullscreen mode Exit fullscreen mode

Page numbers in footers help readers locate sections referenced in the TOC.

Quick Reference

Task Approach
Auto TOC TableOfContents = TableOfContentsTypes.WithLinks
Place TOC <div id='ironpdf-toc'></div>
Style TOC Target .ironpdf-toc-* CSS classes
Add bookmark pdf.Bookmarks.AddBookMarkAtEnd("Title", pageIndex)
Nest bookmarks parent.Children.AddBookMarkAtEnd(...)
Read bookmarks pdf.Bookmarks.GetAllBookmarks()

A good table of contents transforms a long PDF from a wall of text into a navigable document. Let readers jump straight to what they need.

For more navigation options, see the IronPDF table of contents documentation.


Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)