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

Next.js中html2canvas+jsPDF生成PDF标题样式异常求助

Next.js中html2canvas+jsPDF生成PDF样式丢失的修复方案

问题描述

在Next.js项目中使用html2canvas与jsPDF生成PDF时,出现标题标签(h1-h6)样式与p标签无区别的问题,无法还原原HTML的样式效果,需要仅用这两个工具修复该问题。

相关截图:

原代码:

"use client";
import { useRef } from "react";
import jsPDF from "jspdf";
import html2canvas from "html2canvas";

export default function Pdf() {
  const reportTemplateRef = useRef(null);
  const handleDownloadPdf = async () => {
    const element = reportTemplateRef.current;
    if (element) {
      const canvas = await html2canvas(element);
      const data = canvas.toDataURL("image/png");

      const pdf = new jsPDF("l", "pt", "a4");
      pdf.html(document.getElementById("testing"), {
        callback: function () {
          pdf.save("print.pdf");
        },
      });
    }
  };
  return (
    <div>
      <div ref={reportTemplateRef} id="testing" className="view">
      <h1>hello world</h1>
      <h2>hello woerld</h2>
      <h3>hello world</h3>
      <h4>hello world</h4>
      <h5>hello world</h5>
      <h6>hello world</h6>
      <br />
      <p>
        hello world Lorem ipsum dolor, sit amet consectetur adipisicing elit.
        Quis voluptate laboriosam odit tempora impedit ab, veritatis repellendus
        aut! Molestiae nostrum cum dolores vitae, minus veniam alias architecto
        maiores officia dignissimos.
      </p>
      </div>
      <div className="button">
        <button onClick={handleDownloadPdf}>Download</button>
      </div>
    </div>
  );
}

问题根源

你的代码同时混用了两种PDF生成逻辑:

  • 用html2canvas生成了DOM的canvas截图,但未实际使用
  • 调用jsPDF的html()方法直接渲染DOM,该方法在Next.js客户端组件环境中,无法正确加载模块化样式(如CSS Modules、Tailwind),导致标题样式丢失

修复方案

改用html2canvas生成的canvas图片构建PDF,完全还原页面渲染的样式效果:

修改后的代码:

"use client";
import { useRef } from "react";
import jsPDF from "jspdf";
import html2canvas from "html2canvas";

export default function Pdf() {
  const reportTemplateRef = useRef(null);
  const handleDownloadPdf = async () => {
    const element = reportTemplateRef.current;
    if (!element) return;

    // 渲染目标元素为canvas,提高分辨率避免模糊
    const canvas = await html2canvas(element, {
      scale: 2,
      useCORS: true, // 若包含外部跨域图片需开启
    });

    const imgData = canvas.toDataURL("image/png");
    const pdf = new jsPDF("l", "pt", "a4");
    
    // 计算图片在PDF中的适配尺寸
    const imgWidth = pdf.internal.pageSize.getWidth();
    const imgHeight = (canvas.height * imgWidth) / canvas.width;

    // 将canvas图片插入PDF
    pdf.addImage(imgData, "PNG", 0, 0, imgWidth, imgHeight);
    pdf.save("print.pdf");
  };

  return (
    <div>
      <div ref={reportTemplateRef} id="testing" className="view">
        <h1>hello world</h1>
        <h2>hello world</h2>
        <h3>hello world</h3>
        <h4>hello world</h4>
        <h5>hello world</h5>
        <h6>hello world</h6>
        <br />
        <p>
          hello world Lorem ipsum dolor, sit amet consectetur adipisicing elit.
          Quis voluptate laboriosam odit tempora impedit ab, veritatis repellendus
          aut! Molestiae nostrum cum dolores vitae, minus veniam alias architecto
          maiores officia dignissimos.
        </p>
      </div>
      <div className="button">
        <button onClick={handleDownloadPdf}>Download</button>
      </div>
    </div>
  );
}

注意事项

  • 确保目标元素的样式为全局样式或内联样式,若使用CSS Modules需确认样式已正确作用到元素上
  • 调整scale参数可平衡PDF清晰度与文件体积,值越高清晰度越好但体积越大
  • 若内容超出单页,需额外实现分页逻辑(可根据canvas高度拆分图片后逐页添加)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:55:32