PDF Bookmark Guidelines
1. Introduction
This guide explains how to create and control PDF bookmarks in templates rendered by WeasyPrint and PrinceXML.
PDF bookmarks appear in the navigation panel of a PDF viewer. They allow users to quickly move to important sections of a document.
The goal of this guide is to help template developers:
- Create bookmarks for document sections.
- Control the bookmark level.
- Remove bookmarks from specific headings.
- Set a custom bookmark label.
- Keep bookmark behavior consistent across WeasyPrint and PrinceXML.
2. Basic Concept
Bookmarks are created from HTML elements by using CSS.
A bookmark has two main parts:
- Bookmark level --- defines where the bookmark appears in the bookmark tree.
- Bookmark label --- defines the text displayed in the bookmark panel.
For example:
<h1>Introduction</h1>
<h2>Background</h2>
<h2>Objectives</h2>
<h1>Implementation</h1>
can produce:
Introduction
Background
Objectives
Implementation
The bookmark hierarchy does not have to exactly match the visual appearance of the document. CSS can control it separately.
3. Create and control bookmarks
WeasyPrint and PrinceXML support the same bookmark concepts. The only difference for bookmark levels and labels is the CSS property name:
| Purpose | WeasyPrint | PrinceXML |
|---|---|---|
| Set bookmark level | bookmark-level | -prince-bookmark-level |
| Remove bookmark | bookmark-level: none | -prince-bookmark-level: none |
| Set bookmark label | bookmark-label | -prince-bookmark-label |
The examples below use the WeasyPrint property names. For PrinceXML,
replace bookmark-level with -prince-bookmark-level and
bookmark-label with -prince-bookmark-label.
3.1 Create bookmarks from headings
A common approach is to use HTML headings:
<h1>Introduction</h1>
<h2>Background</h2>
<h2>Objectives</h2>
<h1>Implementation</h1>
You can explicitly define the bookmark levels:
h1 {
bookmark-level: 1;
}
h2 {
bookmark-level: 2;
}
h3 {
bookmark-level: 3;
}
The resulting PDF bookmark tree is:
Introduction
Background
Objectives
Implementation
Recommended practice
Use semantic HTML headings:
h1for major sections.h2for sections inside anh1.h3for sections inside anh2.
This makes the document structure easier to understand and maintain.
3.2 Remove a bookmark
Use:
bookmark-level: none;
For example, to prevent all h2 elements from becoming bookmarks:
h1 {
bookmark-level: 1;
}
h2 {
bookmark-level: none;
}
h3 {
bookmark-level: 3;
}
The h2 elements will still be visible in the document. They will
simply not appear in the PDF bookmark panel.
Remove a bookmark from one element
Use a class when only some headings should be excluded:
<h2 class="no-bookmark">Internal Details</h2>
<h2>Public Details</h2>
.no-bookmark {
bookmark-level: none;
}
Only Internal Details is excluded.
3.3 Create a bookmark from a non-heading element
A bookmark does not have to come from an h1--h6.
For example:
<div class="chapter-title">Chapter 1 — Introduction</div>
.chapter-title {
bookmark-level: 1;
}
This creates a level 1 bookmark for the <div>.
This can be useful when your template uses custom components instead of normal HTML headings.
3.4 Set a custom bookmark label
By default, the bookmark label normally comes from the element's content.
You can set a custom label with:
h1 {
bookmark-label: 'Introduction';
}
You can also use the element's content:
h1 {
bookmark-label: content();
}
For example:
<h1>Annual Report</h1>
h1 {
bookmark-level: 1;
bookmark-label: content();
}
The bookmark will be:
Annual Report
3.5 Use an HTML attribute for the bookmark label
This is useful when the visible heading and the PDF bookmark should have different text.
<h1 class="chapter-title" data-bookmark="Executive Summary">
Executive Summary and Business Overview
</h1>
.chapter-title {
bookmark-level: 1;
bookmark-label: attr(data-bookmark);
}
The document displays:
Executive Summary and Business Overview
while the PDF bookmark displays:
Executive Summary
Recommended practice
For reusable templates, data-bookmark is a good way to give template
developers explicit control over bookmark text.
3.6 Control the bookmark state
WeasyPrint supports:
bookmark-state
For example:
h1 {
bookmark-level: 1;
bookmark-state: open;
}
h2 {
bookmark-level: 2;
bookmark-state: closed;
}
This controls whether bookmark children are initially expanded or collapsed in the PDF viewer.
Use this carefully. For large documents, keeping lower-level bookmarks collapsed can make the navigation panel easier to use.
4. Recommended Cross-Engine Template Pattern
If the same template can be rendered by both engines, use a common HTML convention.
For example:
<h1 class="document-section" data-bookmark="Introduction">Introduction</h1>
<h2 class="document-section" data-bookmark="Background">
Background and Context
</h2>
Then provide engine-specific CSS.
.document-section.level-1 {
bookmark-level: 1;
bookmark-label: attr(data-bookmark);
-prince-bookmark-level: 1;
-prince-bookmark-label: attr(data-bookmark);
}
.document-section.level-2 {
bookmark-level: 2;
bookmark-label: attr(data-bookmark);
-prince-bookmark-level: 2;
-prince-bookmark-label: attr(data-bookmark);
}
HTML:
<h1 class="document-section level-1" data-bookmark="Introduction">
Introduction
</h1>
<h2 class="document-section level-2" data-bookmark="Background">
Background and Context
</h2>
This approach keeps the HTML independent from the rendering engine and both engines still can use one CSS style file.
PrinceXML also supports bookmark-level, bookmark-label, bookmark-state
as an alias of -prince-bookmark-level, -prince-bookmark-label and -prince-bookmark-state.
You can use same syntax and they can be rendered by both engines WeasyPrint and PrinceXML.
5. Recommended Bookmark Convention
For a shared template system, use the following convention:
HTML Bookmark Level Recommended Use
h1: Main document section
h2: Section
h3: Subsection
h4: Detailed subsection
h5 / h6: Usually none. Use only when needed
Example:
<h1>Introduction</h1>
<h2>Background</h2>
<h3>History</h3>
<h3>Current Situation</h3>
<h2>Objectives</h2>
<h1>Implementation</h1>
<h2>Architecture</h2>
<h3>Frontend</h3>
<h3>Backend</h3>
Recommended bookmark tree:
Introduction
Background
History
Current Situation
Objectives
Implementation
Architecture
Frontend
Backend
Avoid creating too many bookmark levels. A deep bookmark tree can make the PDF difficult to navigate.
Do not use very long bookmark labels.
Prefer:
Executive Summary
Financial Results
Implementation
Conclusion
Instead of:
Chapter 3 - Financial Results and Detailed Analysis of the Company's Financial Performance During the Reporting Period
The bookmark panel has limited width, so short and meaningful labels are easier to use.
If the visible heading is too long, use data-bookmark to provide a shorter
label:
<h1 data-bookmark="Financial Results">
Chapter 3 — Financial Results and Detailed Analysis
</h1>
6. Bookmarks and Table of Contents
PDF bookmarks and a printed Table of Contents are different features.
PDF bookmarks
Appear in the PDF viewer's navigation panel:
Introduction
Background
Objectives
Implementation
Architecture
Table of Contents
Appears as a page inside the document:
Table of Contents
Introduction ...................... 3
Background .................... 4
Objectives .................... 5
Implementation .................... 7
Architecture .................. 8
A document can have:
- Bookmarks without a printed TOC.
- A printed TOC without bookmarks.
- Both bookmarks and a printed TOC.
For a professional document, using both is recommended when the document is large.
Please check Table of Contents section to learn how to create it.