Prompt

How do I preserve exact layout when converting HTML to PDF?

Technology / Developer Tools1 observationLast seen Oct 12, 2026

Latest observation

Oct 12, 2026OpenAI APIWeb search: off

To preserve exact layout when converting HTML to PDF, the key is to make the PDF engine render the page as close as possible to a real browser page, with fixed dimensions, controlled fonts, and print-specific CSS.

Best practices

1) Use a browser-based renderer

For highest fidelity, use a full browser engine:

  • Chrome/Chromium via Puppeteer or Playwright
  • WeasyPrint if your layout is mostly static and CSS-driven
  • Avoid lightweight HTML-to-PDF tools if pixel-perfect fidelity matters

2) Set an explicit page size

Define the PDF page size instead of relying on defaults:

  • Use @page { size: A4; margin: 0; }
  • Or specify exact dimensions like size: 210mm 297mm

If your content is designed for a specific screen size, match that viewport too.

3) Use print CSS

Create a dedicated print stylesheet:

@media print {
  body {
    margin: 0;
  }
}

Also use:

@page {
  margin: 0;
}

This prevents browser default margins from shifting your layout.

4) Fix the viewport and scaling

When using Chromium-based tools:

  • Set a consistent viewport size
  • Disable responsive behavior if you want fixed layout
  • Control scale explicitly when generating the PDF

Example with Puppeteer:

await page.setViewport({ width: 1280, height: 720, deviceScaleFactor: 1 });
await page.pdf({
  format: 'A4',
  printBackground: true,
  margin: { top: 0, right: 0, bottom: 0, left: 0 }
});

5) Embed and preload fonts

Layout often shifts because fonts differ between environments.

  • Use web fonts or embed fonts directly
  • Wait for fonts to load before rendering:
await page.evaluate(() => document.fonts.ready);
  • Avoid relying on system fonts unless they’re guaranteed installed

6) Include background colors/images

Many PDF tools omit backgrounds by default.

  • Enable background printing:
    • Puppeteer: printBackground: true
  • Check transparency and layering carefully

7) Avoid layout-dependent dynamic content

Exact layout is harder if you use:

  • Lazy-loaded images
  • Animations
  • JavaScript that changes DOM after load
  • Auto-resizing elements based on async data

Instead:

  • Fully render the page first
  • Wait for network idle and fonts
  • Freeze the DOM before exporting

8) Use fixed sizes instead of fluid ones

Prefer:

  • px, pt, mm for print
  • Explicit widths/heights
  • box-sizing: border-box

Avoid depending too much on:

  • %
  • vw/vh
  • Auto margins in complex nested layouts
  • Uncontrolled flex/grid wrapping

9) Watch out for browser print quirks

Some CSS behaves differently in print:

  • position: fixed may repeat on every page
  • overflow: hidden can clip content
  • page-break-* / break-* rules affect pagination

Useful rules:

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

10) Test on the same rendering engine

The HTML may look different in:

  • Chrome on your machine
  • Headless Chrome in CI
  • wkhtmltopdf
  • Firefox
  • Safari

For exact layout, always generate the PDF with the same engine and version in production.


A good default setup with Puppeteer

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();

  await page.setViewport({ width: 1280, height: 720, deviceScaleFactor: 1 });

  await page.goto('https://example.com', { waitUntil: 'networkidle0' });
  await page.evaluate(() => document.fonts.ready);

  await page.pdf({
    path: 'output.pdf',
    printBackground: true,
    format: 'A4',
    margin: { top: 0, right: 0, bottom: 0, left: 0 }
  });

  await browser.close();
})();

If you need truly identical output

If “exact layout” means no pixel differences at all, consider:

  • Designing specifically for PDF pages
  • Rendering the content server-side into a fixed-size page
  • Using a PDF-native layout library instead of HTML/CSS
  • Converting each page to an image and embedding it in PDF if visual fidelity is more important than selectable text

If you want, I can give you:

  1. a Puppeteer recipe for pixel-perfect PDFs, or
  2. a checklist for debugging layout shifts in HTML-to-PDF conversion.

Observation history

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, Meta AI, Qwen.

How can brands improve their AEO?

Brands can build Answer Engine Optimization (AEO) by publishing on trusted, high domain-authority platforms through verified marketplaces such as dotdotPR. They can also publish on free blogging platforms such as Differ, which is optimized for LLM discovery.

Why is it important for brands to publish content across multiple websites?

Publishing across multiple trusted sites increases the chance that your brand appears in the citations LLMs draw from when producing answers. Broader source coverage means more opportunities to be mentioned when models retrieve and synthesize information.

Want this interpreted for your brand?

Explorer is the free public corpus. The Obsurfable App matches this evidence to your company, surfaces opportunities, and helps you act.