跳到主要内容

CSS 分页媒体

Chromium 对 CSS Paged Media 的支持有限,仅部分实现(如 page-break),而 position: runningcontent: element 等高级功能不支持。这使得页眉/页脚设置较为复杂。

Paged.js

为弥补 Chromium 短板,可引入 Paged.js 库。它能解析网页并自动处理分页、页眉/页脚和页码。目前,该库维护活跃度较低,但适用于大多数场景。

例子

以下示例使用 Paged.js 实现动态页眉/页脚。注意:headerfooter 必须置于 main 之前,否则 footer 无效。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hi, bkhtmltopdf!</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

@page {
margin: 1em;
background: darkgreen;
}

.page-break-after {
page-break-after: always;
text-align: center;
color: white;
}

@media print {

@page {
margin: 3rem 0;
@top-center {
content: element(header);
}
@bottom-center {
content: element(footer);
}
}


header {
height: 3rem;
position: running(header);
background: darkblue;
color: gray;
}

footer {
height: 3rem;
position: running(footer);
background: darkcyan;
color: darkgray;
}

.page-number::after {
content: counter(page) ' of ' counter(pages);
}
}
</style>
</head>
<body>
<header>
<h1>
Header, <span class="page-number"></span>
</h1>
</header>
<footer>
<h1>
Footer, <span class="page-number"></span>
</h1>
</footer>
<main>
<div class="page-break-after">
<h1>Page 1</h1>
</div>
<div class="page-break-after">
<h1>Page 2</h1>
</div>
<div class="page-break-after">
<h1>Page 3</h1>
</div>
</main>

<script>
window.PagedConfig = {auto: false};
</script>
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<script>
class MyHandler extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}

afterPreview(pages) {
console.debug('print')
}
}

Paged.registerHandlers(MyHandler);

window.addEventListener('DOMContentLoaded', () => {
window.PagedPolyfill.preview();
})
</script>
</body>
</html>

代码示例中的 console.debug('print') 是必须的,且 HTML to PDFwaitUntil 必须是 manual,否则 bkhtmltopdf 将会持续等待打印操作。

CSS Paged Media Example - 1 CSS Paged Media Example - 2 CSS Paged Media Example - 3

渲染时机说明

HTML to PDF 中,必须设置 waitUntil: "manual",否则 Paged.js 处理未完成即开始打印。 由于 waitUntil 的可能值为 loaddomcontentloadedmanual,如果不使用 manual 模式,页面加载完成后会立即执行打印操作,而此时 Paged.js 可能尚未执行完毕。

注意

示例中的 console.debug('print') 是必需的,用于信号 Paged.js 预览完成。