When i try to use jsPDF and html2canvas to build a pdf from my webpage, it does work, but everything is smaller, if res is 1080x800 the pdf is fine

i’m using the below function

const saveAsPDF = async () => {
    const pdf = new jsPDF({
      orientation: 'p',
      unit: 'mm',
      format: 'a4'
    });

    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();
    const margin = 15; // Margin around the content

    // Function to add the header with the border, logo, and title
    const addHeaderToPDF = () => {
      const borderMargin = 5;
      const borderWidth = pageWidth - 2 * borderMargin;
      const borderHeight = pageHeight - 2 * borderMargin;
      const borderRadius = 5; // Rounded corners

      // Draw the rounded border
      pdf.setLineWidth(0.5);
      pdf.setDrawColor(128, 128, 128);
      pdf.roundedRect(borderMargin, borderMargin, borderWidth, borderHeight, borderRadius, borderRadius, 'D');

      // Add the logo
      const logoWidth = 25; // Adjust logo size
      const logoHeight = 10;
      const logoYPosition = borderMargin + 10; // Position logo

      pdf.addImage(ClientLogo, 'PNG', (pageWidth - logoWidth) / 2, logoYPosition, logoWidth, logoHeight);

      // Add the title
      pdf.setFontSize(18);
    //   pdf.setFont('helvetica', 'bold');
    //   const title = `Onboarding info for ${payload.FIRST_NAME || ''} ${payload.MIDDLE_NAME || ''} ${payload.LAST_NAME || ''}`.trim();
    //   pdf.text(title, pageWidth / 2, logoYPosition + logoHeight + 10, { align: 'center' });
    };

    // Function to add content to PDF
    // const addContentToPDF = async (contentId, yPosition) => {
    //   const content = document.getElementById(contentId);
    //   if (content) {
    //     const children = Array.from(content.children);

    //     pdf.setFontSize(14);

    //     for (const child of children) {
    //       const canvas = await html2canvas(child, { scale: 2, useCORS: true });
    //       const imgHeight = (canvas.height * (pageWidth - 2 * margin)) / canvas.width;

    //       if (yPosition + imgHeight > pageHeight - margin) {
    //         pdf.addPage();
    //         addHeaderToPDF();
    //         yPosition = margin;
    //       }

    //       const imgData = canvas.toDataURL('image/jpeg', 0.8);
    //       const imgWidth = pageWidth - 2 * margin;

    //       pdf.addImage(imgData, 'JPEG', margin, yPosition, imgWidth, imgHeight);
    //       yPosition += imgHeight;
    //     }
    //   }
    //   return yPosition;
    // };
    const addContentToPDF = async (contentId, yPosition) => {
      const content = document.getElementById(contentId);
      if (content) {
        const children = Array.from(content.children);
        const spaceAbove = 20; // Space to leave at the top for the logo and header
    
        pdf.setFontSize(14);
    
        for (const child of children) {
          const canvas = await html2canvas(child, { scale: 2, useCORS: true });
          const imgHeight = (canvas.height * (pageWidth - 2 * margin)) / canvas.width;
          const imgWidth = pageWidth - 2 * margin;
    
          // Add space above if it's the first child or if it's a new page
          if (yPosition === margin) {
            yPosition += spaceAbove;
          }
    
          if (yPosition + imgHeight > pageHeight - margin) {
            pdf.addPage();
            addHeaderToPDF(); // Add header on new page
            yPosition = margin + spaceAbove; // Leave space at the top for the logo
          }
    
          const imgData = canvas.toDataURL('image/jpeg', 0.8);
    
          pdf.addImage(imgData, 'JPEG', margin, yPosition, imgWidth, imgHeight);
          yPosition += imgHeight;
        }
      }
      return yPosition;
    };
    

    // Function to add multiple sections to the PDF
    const addSectionsToPDF = async (sections) => {
      let yPosition = margin+10;

      for (const section of sections) {
        if (section === 'otherReference') {
          pdf.addPage();
          addHeaderToPDF();
          yPosition = margin;
        }
        console.log(section)
        if (section === 'images-content') {
          console.log("inside image")
          pdf.addPage();
          addHeaderToPDF();
          yPosition = margin;
        }
        yPosition = await addContentToPDF(section, yPosition);
        yPosition += margin;
        if (yPosition + margin > pageHeight) {
          pdf.addPage();
          addHeaderToPDF();
          yPosition = margin;
        }
      }
    };

    addHeaderToPDF();
    await addSectionsToPDF(['view-auth-content', 'images-content']);

    // Save the PDF
    pdf.save(`${payload.FIRST_NAME}_${data.transactionId}.pdf`);
  };

Once i do it in a default screen size the pdf is way small making it difficult to read, if i open console docked to my right side and set the resolution to 1080x800 the pdf is just fine

i have tried re-sizing the page to fit the given resolution and doesnt work well, my pdf is 2-3 pages long please advise

I’d be glad to help you create PDFs with consistent layout and content size across different screen resolutions using jsPDF and html2canvas. Here’s a revised version of your code incorporating the best aspects of the previous responses and addressing potential issues:

Key Considerations:

  • Fixed Units and Margins:
    • Use fixed units like millimeters (mm) for page dimensions, margins, and font sizes. This ensures consistent layout regardless of screen size.
    • Set standard A4 page size (210mm x 297mm) and define margins (e.g., 20mm) for the content area.
  • Dynamic Content Scaling:
    • Calculate the scaling factor for HTML elements dynamically based on the available content area. This ensures content fits proportionally within the margins.
    • Consider using a base scaling factor (e.g., 1) and adjust it based on the ratio of available width to the element’s original width.
  • Break Logic:
    • Maintain your logic that checks for page breaks based on content height and available space. This ensures content doesn’t overflow onto a new page unnecessarily.
  • Additional Tips:
    • Check for browser compatibility issues with jsPDF and html2canvas.
    • Consider using a responsive design approach for the content you’re converting to PDF to improve adaptability across different screen sizes.

Revised Code:

JavaScript

const saveAsPDF = async () => {
  const pdf = new jsPDF({
    orientation: 'p',
    unit: 'mm',
    format: [210, 297] // A4 size in millimeters
  });

  const margin = 20; // Fixed margin in mm
  const usableWidth = pdf.internal.pageSize.getWidth() - 2 * margin;

  // Function to add the header with the border, logo, and title
  const addHeaderToPDF = () => {
    // ... your existing addHeaderToPDF implementation
  };

  // Function to add content to PDF
  const addContentToPDF = async (contentId, yPosition) => {
    const content = document.getElementById(contentId);
    if (content) {
      const children = Array.from(content.children);

      pdf.setFontSize(14); // Fixed font size
      const baseScale = 1; // Base scaling factor

      for (const child of children) {
        const originalWidth = child.offsetWidth; // Get original element width
        const scaleFactor = Math.min(1, usableWidth / originalWidth) * baseScale; // Dynamic scaling

        const canvas = await html2canvas(child, { scale: scaleFactor, useCORS: true });
        const imgHeight = (canvas.height * scaleFactor);

        if (yPosition + imgHeight > pdf.internal.pageSize.getHeight() - margin) {
          pdf.addPage();
          addHeaderToPDF();
          yPosition = margin;
        }

        const imgData = canvas.toDataURL('image/jpeg', 0.8);
        pdf.addImage(imgData, 'JPEG', margin, yPosition, usableWidth, imgHeight);
        yPosition += imgHeight;
      }
    }
    return yPosition;
  };

  // Function to add multiple sections to the PDF
  const addSectionsToPDF = async (sections) => {
    let yPosition = margin + 10; // Initial position with extra space

    for (const section of sections) {
      if (section === 'otherReference') {
        pdf.addPage();
        addHeaderToPDF();
        yPosition = margin;
      }
      console.log(section);
      if (section === 'images-content') {
        console.log("inside image");
        pdf.addPage();
        addHeaderToPDF();
        yPosition = margin;
      }
      yPosition = await addContentToPDF(section, yPosition);
      yPosition += margin;
    }
  };

  addHeaderToPDF();
  await addSectionsToPDF(['view-auth-content', 'images-content']);

  // Save the PDF
  pdf.save(`${payload.FIRST_NAME}_${data.transactionId}.pdf`);
};

Explanation:

  • The code sets fixed units (mm) for page size, margins, and font size.
  • The addContentToPDF function calculates a dynamic scaling factor for each HTML element based on the available content area and the element’s original width.
  • The break logic remains to ensure content doesn’t overflow onto a new page unnecessarily.
  • Comments are added for clarity.

By incorporating these changes,