reportgen
Back to all posts

CSS vs API in HTML-to-PDF: Who Actually Controls Margins and Backgrounds? 🎯

February 14, 2026

You set margin in the API request. Your PDF still has no margin.

You set print_background: false. Your background still prints.

This is not random. It is often a CSS precedence issue.

In HTML-to-PDF, your template is still a web page, and print CSS can override overlapping API settings.


The Short Version

If you define print rules in template CSS, CSS is often the effective source of truth for overlapping print properties.

  • @page { margin: ... } can override API margin.
  • -webkit-print-color-adjust: exact / print-color-adjust: exact can force colors and backgrounds even when print_background is false.

So API fields like margin and print_background are best treated as defaults/fallbacks in conflicts, not hard guarantees.


Why This Happens

Under the hood, rendering is browser print behavior (Chromium/Puppeteer-style semantics).

That means:

  1. The document still applies print CSS rules.
  2. @page directly affects the printed page box.
  3. Color adjustment rules can change whether background-like styling is preserved.

If you set conflicting instructions in both places (API + CSS), CSS often wins for those overlapping properties.


Margin Example: Why margin: 100px Might Do Nothing

API request

{
  "engine": "raw",
  "html_template": "<html>...</html>",
  "margin": { "top": "100px", "right": "0px", "bottom": "0px", "left": "0px" }
}

Template CSS (conflicting)

@page { margin: 0; }

Result: top margin from the API may not appear, because @page is forcing 0.


Background Example: Why print_background: false Might Still Show Color

API request

{
  "engine": "raw",
  "html_template": "<html>...</html>",
  "print_background": false
}

Template CSS (conflicting)

.hero {
  background: linear-gradient(180deg, #ff3b30, #ff9500);
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

Result: color may still appear in output, because print color adjustment is forcing fidelity.


Recommended Rule: Pick One Primary Source of Truth Per Property

To avoid surprises, choose one owner for print styling:

  • CSS-first (recommended for teams with template control): keep layout and print behavior in template CSS (@page, html/body, color rules).
  • API-first (quick defaults): use API margin and print_background, but avoid conflicting print CSS.

Do not mix both for the same property unless you intentionally understand precedence.


Copy-Paste Baselines

A) CSS-first full-bleed baseline

<style>
  @page { margin: 0; }
  html, body { margin: 0; padding: 0; }
  .bleed {
    width: 100vw;
    height: 100vh;
    background: linear-gradient(180deg, #ff3b30 0%, #ff9500 100%);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
</style>

Use API:

{
  "print_background": true,
  "margin": { "top": "0px", "right": "0px", "bottom": "0px", "left": "0px" }
}

B) API-first margin baseline

<style>
  html, body { margin: 0; padding: 0; }
  /* No @page margin rule here */
</style>

Use API:

{
  "margin": { "top": "24px", "right": "24px", "bottom": "24px", "left": "24px" },
  "print_background": false
}

C) Full simple request example

{
  "engine": "raw",
  "html_template": "<!doctype html><html><head><meta charset=\"utf-8\" /><style>html, body { margin: 0; padding: 0; } @page { margin: 0; } .bleed { width: 100vw; height: 100vh; background: linear-gradient(180deg, #FF3B30 0%, #FF9500 100%); color: white; display: flex; align-items: center; justify-content: center; }</style></head><body><div class=\"bleed\">FULL BLEED TEST</div></body></html>",
  "print_background": true,
  "margin": {
    "top": "0px",
    "right": "0px",
    "bottom": "0px",
    "left": "0px"
  }
}

Debug Checklist

If output does not match request settings, check these first:

  1. Is there an @page rule in template CSS?
  2. Is print-color-adjust or -webkit-print-color-adjust set to exact?
  3. Are you setting the same property in both API and CSS?
  4. Does Chrome print preview match what you expect from this HTML?

Most layout mysteries are solved by those four checks.


Final Takeaway

For HTML-to-PDF, CSS is not a side detail. It strongly shapes print output.

Use API settings as convenience defaults, but treat template print CSS as authoritative where it overlaps.

When in doubt: simplify, remove conflicting rules, and choose a single source of truth for each print property.