Inconsistent text scaling when creating PDFs with Puppeteer from HTML content

I’m working on a project where I need to create PDF documents using Puppeteer by converting HTML content. The HTML gets built dynamically with EJS templates because I have variable data like pictures, tables with changing rows/columns, and text blocks.

I’ve set up CSS styles inside a style block to control how everything looks. However, I’m running into a weird problem where the text size appears inconsistent across different PDFs. Some documents look normal while others appear shrunk down, almost like the browser zoom got changed to 80% instead of 100%.

When I remove image elements from the HTML (they don’t have special CSS), the sizing issue goes away for certain data combinations. I’m also seeing content get trimmed on the right side sometimes, even after setting the body width to 100%.

The strange thing is that when I open the same HTML file directly in a browser, everything looks identical regardless of the data that caused PDF sizing problems.

Here’s my CSS setup:

* {
    font-size: 16px;
}

And here’s my Puppeteer configuration:

const browserInstance = await puppeteer.launch({
    args: ['--no-sandbox'],
    headless: true
});

await currentPage.setContent(htmlContent, {
    waitUntil: 'networkidle0'
});

const pdfSettings = {
    headerTemplate: topHtmlWithStyles,
    footerTemplate: bottomHtmlWithStyles,
    displayHeaderFooter: true,
    margin: {
        top: "195px",
        right: "64px", 
        bottom: "100px",
        left: "64px"
    },
    printBackground: false,
    path: outputPath,
    format: 'A4',
    preferCSSPageSize: false
}

await currentPage.emulateMediaType("screen");
await currentPage.pdf(pdfSettings);

Any suggestions for fixing this scaling inconsistency would be really helpful.

Had the same nightmare with Puppeteer PDF generation. The scaling mess happens because Puppeteer treats each render as a fresh browser session - images screw with document flow calculations differently every time.

Your universal CSS selector’s part of the problem, but fixing that won’t solve the real issue. Puppeteer’s print engine just sucks for complex dynamic content.

I was going crazy with the same problems until I moved everything to automation. Now I use Latenode for PDF generation. Instead of fighting Puppeteer’s quirks, you build a workflow that processes your EJS data, normalizes image dimensions first, then generates PDFs with a stable engine that actually works.

The workflow approach gives you control over each step. Images get processed to consistent sizes before hitting the PDF generator. Text scaling stays predictable because you’re not dealing with Puppeteer’s browser simulation garbage.

Using this setup for months now - zero scaling issues. Way more reliable than endlessly debugging Puppeteer settings and launch args.

Had this exact scaling nightmare on a document generation service last year. The problem is how Puppeteer handles content reflow when images load async, even with networkidle0. Different image dimensions mess with the layout engine’s text positioning at different zoom levels.

What fixed it: add explicit width constraints on image containers in CSS, not the images. When images have random dimensions, they push text around during render - that’s your 80% zoom effect. Also ditch that universal font-size rule now. It breaks cascading and forces recalculation on every element.

Add --disable-lcd-text and --disable-gpu to your launch args. These stop font rendering issues that make scaling worse. Set a fixed viewport width matching your content area - about 700px for A4 with those margins. The right-side trimming happens because your content area’s actually narrower than you think with those margin settings.

Same issue here with Puppeteer PDFs. Add --disable-font-subpixel-positioning to your launch args - fixed my text scaling when mixing images and text. Puppeteer renders fonts differently based on page complexity. Your margins also look too big for A4, probably why you’re getting that right-side trimming.

Been there with similar PDF generation headaches. The scaling issues happen because Puppeteer’s rendering engine gets confused with different content layouts, especially dynamic images.

Your CSS approach with the universal selector is making things worse. Setting everything to 16px breaks natural hierarchy and causes weird inheritance issues with images and containers.

You’re trying to manage all this complexity manually. I spent weeks debugging similar Puppeteer setups until I switched to a better approach.

What solved this was moving PDF generation to Latenode. Instead of wrestling with Puppeteer configs and CSS inconsistencies, you set up an automation workflow that handles HTML processing, image rendering, and PDF generation in separate, controlled steps.

Latenode has built-in PDF generation nodes that don’t suffer from scaling issues because they use more stable rendering engines. You feed your EJS template data through the workflow, process images separately for consistent sizing, then combine everything into a PDF with predictable results.

Best part is you can test each step independently. When something looks off, you know exactly where the problem is instead of guessing if it’s CSS, Puppeteer settings, or data combination.

Check it out: https://latenode.com

The issue is inconsistent DPI handling between renders. Puppeteer picks up system display settings that change based on what content you’re processing - that’s why you’re getting the zoom effect. I hit the exact same problem generating invoices with different product images. Here’s what worked: set the page scale factor before loading content with await currentPage.evaluateOnNewDocument(() => { Object.defineProperty(navigator, 'deviceMemory', { get: () => 4 }); }); and throw --force-device-scale-factor=1 into your launch args. That universal font-size selector is causing problems too. It’s overriding browser defaults for everything, but images don’t naturally inherit font sizes. When you force everything to 16px, the browser recalculates image spacing differently based on dimensions. Ditch that CSS rule and use specific selectors for text instead. Also add --disable-dev-shm-usage to your launch args - stops memory issues that mess with rendering on larger content.

This is usually Puppeteer’s viewport handling, not CSS. I ran into the same thing generating reports with mixed content. Puppeteer doesn’t keep device pixel ratios consistent between renders, especially when image sizes vary a lot. Set your viewport before adding content: await currentPage.setViewport({ width: 1200, height: 800, deviceScaleFactor: 1 }). That deviceScaleFactor part is key. Also switch to “print” media instead of “screen” for PDFs - screen media causes weird scaling with print margins. For the trimming, your body width is probably fighting with those fixed margins. With 64px margins on both sides of A4, your actual content width shrinks way more than you’d expect.