You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Puppeteer生成PDF时,能否为第一页和第二页设置不同页眉页脚?

实现Puppeteer PDF第一页与第二页不同页眉页脚的方案

我之前做项目时刚好碰到过一模一样的需求!Puppeteer默认的页眉页脚是全局生效的,但通过CSS配合一些小技巧,完全可以实现第一页和其他页面(比如第二页)的差异化设置,下面分享两种我亲测有效的方案:

方案一:利用CSS @page 伪类(最简洁)

这个方案直接通过CSS打印样式来控制不同页面的页眉页脚,不需要复杂的JS逻辑,适合静态内容的场景。

核心思路

使用CSS的 @page 规则定义全局页眉页脚,再用 @page :first 伪类单独覆盖第一页的样式,同时通过调整页面边距避免内容和页眉页脚重叠。

代码示例

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // 加载自定义HTML内容
  await page.setContent(`
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        /* 全局页面样式(除第一页外) */
        @page {
          margin: 80px 40px; /* 给页眉页脚留足空间 */
          @top-center {
            content: "全局通用页眉";
            font-size: 12px;
            color: #666;
          }
          @bottom-center {
            content: "第 " counter(page) " 页 / 共 " counter(pages) " 页";
            font-size: 12px;
            color: #666;
          }
        }

        /* 第一页专属样式 */
        @page :first {
          margin: 60px 40px; /* 调整第一页边距,避免和全局冲突 */
          @top-center {
            content: "第一页(介绍页)专属页眉";
            font-size: 14px;
            font-weight: bold;
            color: #333;
          }
          @bottom-center {
            content: "介绍页 - 第1页";
            font-size: 12px;
            color: #333;
          }
        }

        body {
          font-family: "Arial", sans-serif;
          line-height: 1.6;
        }

        /* 强制分页,确保第一页和第二页分离 */
        .page-break {
          page-break-after: always;
        }
      </style>
    </head>
    <body>
      <div>
        <h1>欢迎来到介绍页</h1>
        <p>这里是PDF的第一页内容,展示项目介绍、目录等信息...</p>
      </div>
      <div class="page-break"></div>
      <div>
        <h1>第二页内容</h1>
        <p>这里是PDF的第二页,使用全局通用的页眉页脚...</p>
      </div>
      <!-- 更多页面可以继续添加 -->
    </body>
    </html>
  `);
  
  // 生成PDF,开启页眉页脚(模板留空,用CSS控制)
  await page.pdf({
    path: 'custom-pdf.pdf',
    format: 'A4',
    displayHeaderFooter: true,
    headerTemplate: '',
    footerTemplate: ''
  });
  
  await browser.close();
})();

方案二:动态DOM + Puppeteer模板(适合动态内容)

如果你的页眉页脚需要动态数据(比如从后端获取的标题、用户信息),可以结合Puppeteer的页眉页脚模板和页面DOM的类控制,实现更灵活的自定义。

核心思路

  1. 在页面中给第一页和其他页面添加不同的类标识
  2. 定义全局的页眉页脚模板,通过CSS控制第一页隐藏全局模板,显示自定义的DOM元素
  3. 其他页面则隐藏第一页的自定义元素,显示全局模板

代码示例

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  // 假设从后端获取的动态数据
  const firstPageHeader = "项目介绍专属页眉";
  const globalHeader = "文档通用页眉";
  
  await page.setContent(`
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        body {
          font-family: "Arial", sans-serif;
          line-height: 1.6;
        }

        .page-break {
          page-break-after: always;
        }

        /* 打印时的样式控制 */
        @media print {
          /* 第一页隐藏全局页眉页脚模板 */
          .first-page .global-header, .first-page .global-footer {
            display: none;
          }

          /* 其他页面隐藏第一页专属页眉页脚 */
          .non-first-page .first-header, .non-first-page .first-footer {
            display: none;
          }

          /* 第一页专属页眉页脚样式 */
          .first-header, .first-footer {
            position: fixed;
            width: 100%;
            font-size: 12px;
            text-align: center;
            color: #333;
          }
          .first-header {
            top: 20px;
            font-weight: bold;
            font-size: 14px;
          }
          .first-footer {
            bottom: 20px;
          }
        }

        /* 屏幕上隐藏页眉页脚,只在打印时显示 */
        @media screen {
          .first-header, .first-footer, .global-header, .global-footer {
            display: none;
          }
        }
      </style>
    </head>
    <body>
      <div class="first-page">
        <div class="first-header">${firstPageHeader}</div>
        <div class="first-footer">介绍页 - 第1页</div>
        <h1>项目介绍</h1>
        <p>这里是第一页的动态内容...</p>
      </div>
      <div class="page-break"></div>
      <div class="non-first-page">
        <h1>第二页内容</h1>
        <p>这里是第二页的内容,使用全局页眉页脚...</p>
      </div>
    </body>
    </html>
  `);
  
  // 生成PDF,配置全局页眉页脚模板
  await page.pdf({
    path: 'dynamic-pdf.pdf',
    format: 'A4',
    displayHeaderFooter: true,
    headerTemplate: `<div class="global-header">${globalHeader}</div>`,
    footerTemplate: '<div class="global-footer">第 <span class="pageNumber"></span> 页 / 共 <span class="totalPages"></span> 页</div>',
    margin: { top: '60px', bottom: '40px' } // 给页眉页脚留空间
  });
  
  await browser.close();
})();

注意事项

  • 边距调整:一定要给页眉页脚留出足够的边距,避免内容和页眉页脚重叠,建议先在Chrome打印预览中调试边距和样式
  • 测试技巧:开发时可以设置 puppeteer.launch({ headless: false }),打开Chrome的打印预览功能,实时查看样式效果
  • 动态页码:如果需要使用页码变量,Puppeteer的模板支持 pageNumber 和 totalPages 两个内置变量,直接在模板中使用即可

内容的提问来源于stack exchange,提问作者Guru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:03:55