Why Did One 80×80mm Label Print as Two Pages?

A download button exposed one connected engineering problem spanning business identity, filenames, browser pagination and physical dimensions; the fix was to isolate the print document, not shrink the label.

The request began with a small interaction: make “Download PNG” in the label editor open a real Save As flow. After clicking, a user should see a useful suggested filename, choose where to save it and end up with a file that can be identified without opening it.

The first filename implementation immediately exposed a deeper problem. It used an internal SKU such as SKU-001, while the identifier people actually saw and used on the label was Batch No: 30267-0914. The download worked, but the data semantics did not. The system had selected an identifier that existed technically and was wrong operationally.

Production route
/tools/label/
Business identifier for filenames
Visible Batch No, when present
Example
30267-0914-BQ.png · 30267-0914-BQ.pdf
Physical size
No scaling; 80×80mm remains 80×80mm
Pagination verification
Six sizes produced one page each in Chromium

A filename is part of the data model

The answer was not to invent another piece of download-only naming logic that merely looked right. The filename and the visible Batch No now resolve from the same canonical data source. If the label shows 30267-0914, the PNG is suggested as 30267-0914-BQ.png and the PDF as 30267-0914-BQ.pdf. If those values diverge, at least one of them is no longer describing the batch in front of the user.

The same principle applies to PDF, although the browser interface is different. On macOS, when a browser print flow continues to Print → Save as PDF, the suggested PDF name comes from the print document title. The print path therefore replaces document.title briefly with the Batch-derived name before printing, then reliably restores the normal page title when printing ends, is cancelled or the window regains control. This is not a change to the page's SEO title. It is scoped state with an explicit entry and exit around one print session.

Exactly one page became one page plus a blank one

Once the naming path was coherent, the more interesting failure appeared: an 80×80mm label produced two pages in print preview, with the second page blank.

It feels obvious that an 80×80mm sheet should fit on an 80×80mm page. Browser layout, however, does not compare two integer millimetre values directly. CSS millimetres are converted to CSS pixels, and the print pipeline maps those pixels again into device and pagination units. At the page boundary, subpixel rounding, a default line box or a tiny contribution from the document body can place an edge that is numerically “exact” into the next pagination fragment.

The original print sheet was set to the full page dimensions, but it still participated in normal document pagination. Hiding only #root was weaker than it appeared, because it assumed that no other body child could contribute to print layout. That assumption is too broad when the output contract depends on an exact page boundary.

Fix the pagination, not the label dimensions

The correct fix was to isolate the print sheet from normal pagination flow. The print stylesheet strictly removes every non-print body child, zeroes margins, padding and line-box contributions on html and body, and positions the one print sheet absolutely at the page origin. It still retains the exact dynamic rule derived from the current label:

@page { size: <width-mm> <height-mm>; margin: 0; }

There is deliberately no 99% scale, no subtraction of 1mm from either edge and no A4 “fit to page” workaround. Those techniques might remove the blank page, but they would also change the output contract that matters most. An 80×80mm label must remain physically 80×80mm.

The editor and export preview can be enlarged to 150% to make the work surface easier to use, but that is presentation only. Canonical geometry and output pixels stay fixed: 100×100mm still exports as 1000×1000px, and 70×20mm still exports as 700×200px. Looking larger on screen is not the same as printing larger on paper.

Proving it was a pagination fix, not a lucky exception

Verification could not stop at 80×80mm. A special case for one size can create a convincing but fragile “fix.” Chromium pagination checks covered 70×20, 70×40, 80×60, 80×80 and 100×100mm, plus a custom 93×57mm label. All six produced exactly one page.

The automated environment could not directly read the page counter in the native macOS print-preview UI. The evidence boundary matters: the automation proved single-page Chromium print documents across that six-size matrix; it did not pretend to inspect a native UI value that was unavailable to it.

The last step happened outside the browser. After the print hotfix was validated in Production, the production-validated branch was reconciled back to GitHub main, leaving the source tree and the Production tree identical. That closure prevents a solved production bug from returning the next time an incomplete source branch is deployed.

“It downloads” is not done, and “it prints” is not done either. It is done when the data source, filename, physical dimensions, pagination behaviour and production source all agree.

WEOUR / BUILD

Take part in the build

If you are dealing with real cross-border commerce, inventory, warehouse, fulfilment or automation problems, tell us what you need.

Share your requirement Follow WEOUR / community channel — coming later