Skip to content
All articles

The Print Stylesheet Nobody Writes

7 min read

Nobody prints websites, which is true right up until someone does. Invoices, tickets, recipes, packing slips, order confirmations, a CV. And "print" now mostly means save as PDF, which is how a page gets emailed to an accountant or attached to an application — so the printed rendering is often the version that travels furthest from you.

It is also, on most sites, completely unconsidered. Hit Ctrl+P on something you have built and there is a decent chance you get a dark rectangle, a navigation bar, a cookie banner, and the article you wanted cut off after page one.

This is a short list of what actually breaks, in the order it will bite you. This site has a print stylesheet — the whole home page prints as a clean CV — so this is what building one turned up.

1. Your dark theme will cost the reader an ink cartridge

A dark background is the first thing to go. Browsers do not print background colours by default, which sounds like it saves you — until you realise your text is still light grey, and light grey on white is very nearly nothing.

So a print block has to reset both. Force the text dark and the background transparent, and do it for the whole document rather than per component, because you will not find every element that inherited a colour.

The related trap is print-color-adjust: exact. It forces backgrounds to print, and it is right for the rare element whose meaning is its colour — a status badge, a chart key. It is wrong as a blanket rule, unless you enjoy sending someone a solid black A4.

2. Anything fixed or sticky repeats on every page

position: fixed means "relative to the viewport". On paper there is no viewport; there are pages. Behaviour varies by browser and none of the options are good, with the common one being that your sticky header prints on top of the content on every single sheet.

Reset positioning in the print block, and hide the chrome outright: navigation, sticky headers, floating action buttons, the cookie banner, the back-to-top arrow, the theme toggle. None of it can be interacted with on paper, so all of it is noise around the thing they wanted.

The maintainable version is a utility class — this site uses no-print — applied at the point something is created, rather than a growing list of selectors in the print stylesheet that has to be kept in step with the markup. Same principle as anywhere else: put the decision next to the thing it is about.

3. Viewport units have no meaning on paper

100vh, 100vw, min-height: 100dvh — all of them resolve against a viewport that is not there, and the results range from a hero section claiming a full page to a layout collapsing outright.

Anything sized in viewport units needs an explicit print value, usually auto. Multi-column grid layouts want flattening to a single column too: paper is narrow and portrait, and a three-column dashboard reflows into something unreadable long before it reflows into something wrong.

4. Page breaks land in the worst possible place

Left alone, the browser breaks wherever the page happens to end — through the middle of a table row, between a heading and the paragraph it introduces, one line of a three-line card stranded on its own sheet.

Three properties fix most of it. break-inside: avoid on anything that is a unit — a card, a table row, a figure with its caption, a code block. break-after: avoid on headings, so a heading never ends a page. orphans and widows, set to 2 or 3, to stop a single line of a paragraph being left behind or carried over.

Use break-inside: avoid with some restraint. Applied to something taller than a page it cannot be honoured, and you get a large gap where the browser gave up and started a fresh sheet.

5. A link is just blue text now

The reader cannot click it and cannot see where it went. If the destination matters, print it — a rule that appends the href after the link text handles this in one line.

Two refinements make the difference between useful and unbearable. Scope it to external links only, or every internal anchor and every navigation link drags a URL behind it. And skip links whose text already is the URL, or you get the address twice in a row.

6. The content is there but hidden

The one people miss entirely, because on screen the page is complete.

Accordions, tabs, "read more" toggles, collapsed case studies — on paper the reader cannot expand any of it, so whatever is collapsed is simply absent from the document they keep. If it is worth having behind a toggle it is usually worth having on the printout, so expand it in the print block. This site prints its collapsed case studies open for exactly that reason: the point of the paper version is completeness, not fidelity to the screen.

Lazy-loaded images are the same failure wearing different clothes. An image below the fold that has not loaded yet does not appear, so a printed page can be missing the figure the paragraph refers to. Anything that must print needs to be loaded eagerly, or you accept that whether the document is complete depends on how far the reader happened to scroll first.

7. Say who and where it came from

A printed page has no address bar and no browser tab. Handed to someone else, it has nothing on it saying where it is from.

A small print-only block — site name, the URL of the page, a date — costs nothing and makes the artefact self-describing. It is the same instinct as putting the reply address in the body of a form email rather than only in the headers: assume the thing travels away from its context, because that is the entire reason it was printed.

Test it the way it is used

Print preview in one browser is not testing. Save to PDF from at least Chrome and Firefox, at A4 and Letter, and actually read the result — page by page, looking for breaks in the wrong place and content that did not survive.

The whole thing is an afternoon on a page that matters. And it is one of very few afternoons that produces something a stranger might print, keep, and pass to someone else with your name on it — which for a CV is precisely the point.