How can I create a Full-Height, Fixed-Width Web Page PDF using Puppeteer?

I’m trying to make a PDF from markdown that’s one page tall with a fixed A4 width. I want to use this in a VS Code extension.

My exportPDF() function almost works, but there’s a small problem. The height I calculate before printing (calculatePageHeight()) is slightly different from the actual PDF. This causes an extra page in the PDF.

I’m using a fixed-width div to figure out the page height. I think this might be causing the issue, but I’m not sure how to fix it.

Here’s a simplified version of what I’m doing:

async function makePDF(markdown) {
  const html = convertMarkdownToHTML(markdown);
  const height = await calculatePageHeight(html);
  
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  
  await page.setContent(html);
  await page.pdf({
    path: 'output.pdf',
    width: '210mm',
    height: height + 'px',
    printBackground: true
  });
  
  await browser.close();
}

Any ideas on how to get the height just right?

I’ve dealt with this exact problem in a project recently. What worked for me was using a combination of page.evaluate() and document.body.scrollHeight to get the precise height. Here’s a snippet that might help:

const height = await page.evaluate(() => document.body.scrollHeight);
await page.pdf({
  path: 'output.pdf',
  width: '210mm',
  height: height + 'px',
  printBackground: true
});

This approach captures the actual rendered height of the content, which tends to be more accurate than pre-calculating. Also, make sure your CSS isn’t adding any unexpected padding or margins that could throw off the measurements. If you’re still getting an extra page, you might want to subtract a small buffer (like 5-10px) from the height to account for any minor discrepancies.

Hope this helps solve your issue!

I’ve encountered a similar issue before. Instead of calculating the height beforehand, you might want to consider using the ‘format’ option in the page.pdf() method. This automatically sets the dimensions to standard paper sizes. For A4, you could do:

await page.pdf({
path: ‘output.pdf’,
format: ‘A4’,
printBackground: true
});

This approach ensures the PDF adheres to standard A4 dimensions without manual calculations. If you need custom margins, you can add a ‘margin’ property to the options object. This method has consistently produced accurate results in my experience, eliminating the extra page problem you’re facing.

hey charlieLion, have u tried using viewport instead of calculating height? Something like:

await page.setViewport({width: 595, height: 842}); // A4 size in pixels
await page.pdf({format: 'A4', printBackground: true});

this way u don’t need to worry about height calculation. might solve ur problem!