The journal · 19 July 2026 · 8 min read
HTML to PDF page size and orientation: A4, Letter and landscape
A US invoice that comes out A4, a wide financial table crammed into portrait, a page size that changes depending on who opens the file: page size and orientation trip up almost every HTML to PDF setup. Here is how to pin A4 or Letter, switch to landscape for wide content, and why the size sometimes gets ignored.
You generate a US invoice and it comes out A4, slightly too tall and with margins that look off when someone in your office prints it on Letter paper. Or you build a wide financial table, convert it, and the last three columns are cut off because the page rendered in portrait. Page size and orientation seem like they should be trivial, and yet they trip up almost every HTML to PDF setup at least once, usually because the size is set in more than one place and the wrong one wins. Here is how to pin the exact size you want, when to switch to landscape, and why the size sometimes gets ignored entirely.
The short version
Page size and orientation in HTML to PDF are set with the CSS @page { size: ... } rule, or with the format and landscape parameters your rendering engine or API exposes. Use size: Letter for US documents and size: A4 for most of the rest of the world; add landscape for wide tables. If your size is being ignored, it is almost always because the engine's own default or explicit format setting is overriding your CSS, or because a fixed pixel width on your content is forcing the layout regardless of the paper size. Set the size in one place, match the units to physical paper, and let the content be fluid.
A4 versus Letter, and why it matters for US documents
The two page sizes almost every business document uses are A4 and US Letter, and they are not the same. A4 is 210 by 297mm, the international standard used nearly everywhere outside North America. US Letter is 8.5 by 11 inches, roughly 216 by 279mm, so it is a touch wider and noticeably shorter than A4. That difference is small on screen and very real on paper: an invoice laid out for A4 and printed on Letter loses a few millimeters off the bottom and gains whitespace on the sides, and vice versa. For a US audience, Letter is the correct default, and shipping A4 to US customers is a subtle tell that the document was generated without thinking about where it would be printed.
Set it explicitly and stop relying on the engine's guess. In CSS:
@page { size: Letter; } /* US: 8.5 x 11 in */
/* or */
@page { size: A4; } /* international: 210 x 297mm */
You can also give an exact custom size when a document needs one, for example a receipt roll or a label, by specifying two lengths: @page { size: 80mm 200mm; }. Stick to physical units, millimeters or inches, because pixels do not map cleanly to paper and are the source of a lot of "why is my page a weird size" confusion.
Landscape for wide content
Portrait is right for invoices, letters and reports. Landscape is right when the content is wider than it is tall: a spreadsheet-style table with many columns, a Gantt chart, a wide dashboard export, a data grid. Forcing wide content into portrait is how columns get clipped or shrunk to an unreadable size, so match the orientation to the shape of the data.
@page { size: Letter landscape; }
Through an engine or API you usually set orientation with a separate flag rather than in CSS, which is cleaner when the HTML is not yours to edit:
// Puppeteer
await page.pdf({ format: "Letter", landscape: true });
A common real case is financial data. Wide tables of transactions, aged receivables, or a full ledger export rarely fit portrait, and they usually started life somewhere else, often as a bank or card statement you pulled into a sheet. If that is the pipeline, it is worth getting the source clean first: many teams convert the PDF statement into a spreadsheet, tidy the columns, then render the report to a landscape PDF for distribution. Deciding the orientation up front, based on how many columns survive that tidy-up, saves a lot of re-rendering.
Why your page size is being ignored
When you set @page { size: A4 } and the PDF still comes out Letter, or some other size entirely, one of three things is happening.
The first and most common is that the engine has its own size setting that overrides your CSS. In Puppeteer, if you pass a format or a width and height to the PDF call, that wins over the @page rule in your stylesheet. The two are fighting and the engine parameter is stronger. The fix is to set the size in one place only: either drive it entirely from the API or engine parameter, or drive it entirely from CSS, not both. Most teams find the engine parameter more predictable because it does not depend on the stylesheet loading correctly.
The second cause is a fixed pixel width on your content. If your body or a wrapping container has something like width: 1200px, the layout is built to that width regardless of the paper size, so the engine either scales the whole thing down to fit or clips it, and either way the result does not look like the page size you asked for. Let the content be fluid, or set its width in the same physical units as the page, so the layout adapts to the paper instead of fighting it.
The third is a units and scale mismatch. Mixing pixel-based layout with a physical page size, or leaving a non-default scale factor on the render, makes the content land at an unexpected size on the page even when the paper size is correct. Keep the print layout in physical units and leave the scale at its default unless you have a specific reason to change it.
There is a fourth possibility worth ruling out before you spend long on the three above: your @page rule may never be reaching the renderer at all. If other styling is also missing from the output, the size is not being overridden, the stylesheet is being dropped, and the CSS not working in HTML to PDF guide is the place to start instead.
Setting size and orientation through an API
Rendering server side through a browser-based API does not change any of this, because the same Chromium engine applies the same rules. You pass the format and orientation as parameters, which is the reliable single source of truth, and the output matches what you would see in Chrome's own print preview at that size.
curl https://api.sitepdf.com/v1/render \
-H "Authorization: Bearer $SITEPDF_KEY" \
-F url=https://app.example.com/reports/receivables \
-F format=Letter \
-F landscape=true \
-F print_background=true \
-F archive=true
Because the engine is a real, current browser, the page size and orientation behave exactly as the print preview shows, with no surprise scaling. The full parameter list is on the PDF generator API page. If your wide table is also breaking badly across pages, pair this with the controlling HTML to PDF page breaks guide, and the margins, headers and footers guide covers the whitespace and running headers that go alongside the page size.
A quick checklist
| Situation | What to set |
|---|---|
| US invoice or letter | size: Letter or format Letter, portrait |
| International document | size: A4 or format A4, portrait |
| Wide table, ledger or dashboard | Add landscape |
| Receipt, ticket or label | Custom size: 80mm 200mm |
| Size set but ignored | Engine format is overriding CSS; set size in one place only |
| Content clipped or scaled | Remove fixed pixel widths; use fluid or physical units |
Pick Letter or A4 deliberately based on where the document will be printed, switch to landscape when the data is wider than it is tall, and set the size in exactly one place so nothing overrides it. Confirm it in Chrome's print preview at the target size, and the PDF will come out at the dimensions you intended every time. To see how a given page lands at a chosen size without writing any code first, run it through the HTML to PDF converter and check the result.
Written by the team building Sitepdf, an HTML to PDF API that archives every page it renders. The in-browser converter is free to try; early access locks the launch pricing.