ScreenshotNeo

BlogHTML to image & PDF

Why Are CSS Grid Columns Missing in My HTML-to-PDF Output?

Missing grid columns usually point to renderer support, version, or stylesheet differences. Identify the PDF engine, test a minimal grid, and isolate page breaks.

By the ScreenshotNeo team4 October 20266 min read

CSS Grid columns usually disappear in HTML-to-PDF output because the PDF renderer does not support the exact Grid feature in use, runs an older version, or does not receive the stylesheet you expect. First identify the renderer and its deployed version; then verify the print styles and reduce the layout to a minimal explicit-column grid. A page that works in a browser is not proof that a separate PDF engine will render it the same way.

There is no source HTML, CSS, conversion log, or renderer version here, so the steps below are diagnostic paths rather than a claim about one reproduced failure.

1. Identify the PDF renderer and version

“HTML to PDF” describes an outcome, not one rendering engine. A wrapper may drive a browser, use its own layout engine, or call a hosted service. Find the actual executable, library, container image, or service and record its deployed version. Test that runtime, rather than relying on the browser and package versions on a developer’s machine.

This matters even when a renderer says it supports Grid: support can depend on the specific feature and release. For example, WeasyPrint added CSS Grid in version 62.0, released April 30, 2024. Its changelog records support for grid-auto-flow: column in 62.2, released June 4, 2024. Check the version history for the engine you actually use. WeasyPrint changelog.

2. Check that the PDF pipeline receives the right CSS

Confirm that the stylesheet defining the grid is embedded or successfully loaded during conversion. Then inspect print-specific rules and later declarations that may override display or grid-template-columns. Compare the CSS delivered to the PDF renderer with the CSS used by the browser page.

Stylesheet origin and cascade order can also matter. WeasyPrint documents user-agent, author, and user stylesheets; by default, author styles outrank user stylesheets. If the converter supplies a user stylesheet, check whether an author rule overrides it, or whether the expected author stylesheet is missing. WeasyPrint API reference.

3. Reduce the layout to a minimal grid

Start with one container and two short child elements. Use explicit tracks and a basic gap:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    .pdf-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 12px;
    }
    .pdf-grid > div {
      padding: 12px;
      border: 1px solid #777;
    }
  </style>
</head>
<body>
  <main class="pdf-grid">
    <div>First column</div>
    <div>Second column</div>
  </main>
</body>
</html>

Convert this minimal document with the same tool and options as the failing document. If it works, add the original CSS back a piece at a time: track sizing, repeat(), named lines, item placement, nested grids, then page breaks. That tells you which feature or interaction causes the regression.

For WeasyPrint, the stable reference lists basic declarations such as display: grid, grid-template-*, fr, minmax(), and gaps as supported. It also lists features including display: inline-grid, subgrids, repeat(auto-fill, *), and repeat(auto-fit, *) as unsupported or untested. Treat this as a renderer-specific support list, not a guarantee for other engines. WeasyPrint’s CSS Grid reference.

4. Separate track sizing from page fragmentation

Render a short document that fits on one page, then extend it so the grid crosses a page boundary. If the short document works and the longer one fails, investigate row splitting and page-break behavior before rewriting the column definitions.

WeasyPrint’s reference lists fragmentation between rows as supported and fragmentation within rows among unsupported or untested cases. This is a caution about that renderer; other engines may behave differently. WeasyPrint’s CSS Grid reference.

5. Choose a fallback based on the limitation

Once you know which declaration fails in the deployed renderer, choose a targeted fix:

  • Simplify the Grid to features documented by that renderer, such as explicit tracks, if the document can use a simpler layout.
  • Use another layout mechanism that the current renderer supports when its Grid implementation lacks a required feature.
  • Choose a renderer with documented behavior that meets the document’s needs if the required layout cannot be simplified.

Make the decision with the engine’s own documentation and a representative PDF. A renderer comparison published on September 23, 2026 describes different Grid behavior across Chrome headless, wkhtmltopdf, WeasyPrint, and Prince, but it is a vendor comparison rather than primary documentation. Use it as an investigation map, then verify the specific version and output you depend on. Renderer comparison.

6. Troubleshoot common causes

Symptom Likely cause What to check
Grid collapses into one column everywhere in the PDF The renderer lacks support for the declaration, or the Grid stylesheet did not load. Confirm the engine and version; inspect the converted HTML and loaded styles; try the two-column minimal example.
Basic grid works, original grid does not An advanced Grid feature or a declaration interaction is unsupported. Restore original rules incrementally, beginning with track sizing and then placement, nested grids, and auto-repeat patterns.
Browser output works but PDF output does not The browser and PDF pipeline use different engines, versions, or stylesheets. Record the production renderer and compare the CSS that reaches each environment.
Grid works on one page but breaks in a long PDF Page fragmentation or row splitting changes the result. Compare a one-page reproduction with a version that crosses a page boundary; inspect page-break behavior.
A converter stylesheet appears to have no effect Another stylesheet origin or a more specific/later rule wins the cascade. Inspect author and user stylesheets, selector specificity, and declaration order. Confirm the winning computed rule where the renderer permits inspection.
It works locally but fails after deployment The deployed binary, library, or container uses a different version or configuration. Check the production artifact and pin the intended version; rerun the minimal reproduction in that environment.

7. Account for performance, reliability, and cost

For a reliable conversion, keep a small representative HTML fixture alongside the document’s key Grid patterns. Run it through the exact production renderer when changing the renderer version or PDF styles. Include both a one-page case and a case that crosses a page boundary if the real document does.

Do not choose a renderer based only on a generic “Grid supported” label. Compare the exact declarations used, the deployed version, stylesheet loading, pagination behavior, and the resulting PDF. The research available for this topic does not establish conversion speed, reliability rates, or prices for the renderers, so compare those against your actual workload and provider terms.

Or skip the browser setup

For a screenshot or PDF capture without managing a browser renderer, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. The example below captures a PDF; see the ScreenshotNeo API documentation for PDF parameters and other options.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -d format=pdf \
  -o page.pdf
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://stripe.com",
        "format": "pdf",
    },
    timeout=90,
)
r.raise_for_status()
open("page.pdf", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
  format: 'pdf',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
  writeFile('page.pdf', Buffer.from(await res.arrayBuffer()))
);

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server includes take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. These capabilities simplify capture setup, but they do not establish that a particular source page’s CSS Grid will render as intended in PDF: verify the returned document against your layout requirements.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

FAQ

Does CSS Grid work in every HTML-to-PDF converter?

No. Support depends on the renderer, its version, and the specific Grid feature. Verify the deployed engine’s documentation and output.

Is WeasyPrint’s Grid support all-or-nothing?

No. Its reference documents support for basic cases and identifies particular features as unsupported or untested. Check the exact declaration you use.

What should I include in a bug report?

Include a minimal HTML/CSS reproduction, the renderer and version, conversion options, whether the document crosses a page boundary, and the resulting PDF or a description of the output.