The best way to make a web page printable is a short @media print stylesheet plus a few page-break rules. Once you have that, the same page can also become your PDF export.
In Websites Should Be Printable, Brennen Puth hit Ctrl-P on his own blog and didn’t like the result. Here are three levels of print support, what each buys you, and what each still misses.
Table of Contents
- Why print support matters for developers
- Good: let the browser print the page
- Better: a short print stylesheet
- Best: page breaks and PDFs from the same page
- Which level fits your site
- The case against bothering
- FAQ
- Sources
Why print support matters for developers
Printing isn’t only paper. It also covers “Save as PDF” and offline reading, as one developer in the discussion pointed out.
That makes print CSS a product feature. Invoices, tickets, resumes and long articles all get printed or saved as PDFs. A page that prints badly pushes teams toward a separate PDF generator with its own templates.
Good: let the browser print the page
Doing nothing still works. Every browser can print any page.
Puth tried this first. His text came out “too big by about 2 levels”, the header looked bad on paper, and his links turned an unreadable gray in black and white. The content was all there, though.
- Costs: nothing.
- Misses: navigation, screen-sized type, colored links, and anything your layout assumes about screen width.
Better: a short print stylesheet
Puth’s fix was a small @media print block. It does four things:
.onlyPrint { display: none; }
@media print {
.noPrint { display: none; } /* hide the site header */
.onlyPrint { display: inline; } /* show an author line on paper */
p, ol { font-size: 12pt; }
h1 { font-size: 16pt; }
a { color: black !important; } /* gray links vanish in grayscale */
}
Two utility classes control what appears only on screen or only on paper. Body text gets a fixed 12pt size, and links turn black.
- Costs: Puth says it took “a decent chunk of my morning” on a simple site.
- Misses: code blocks. Puth calls them “still the ugliest part” because they break awkwardly across pages.
Best: page breaks and PDFs from the same page
The third level handles the page itself. Another developer called Puth’s stylesheet naive because it leaves out resizing media, keeping elements from splitting, and printing link targets.
Add rules like these on top of level two:
@media print {
pre, figure, table { break-inside: avoid; }
img { max-width: 100%; }
a[href^="http"]::after { content: " (" attr(href) ")"; }
}
break-inside: avoid addresses Puth’s open question about code blocks splitting across pages. Printing the URL after each link keeps the reference on paper.
Then reuse the page for PDFs. One developer in the discussion makes pages printable from the start for this reason. It often heads off the “can users download a PDF?” request, since users already know how to print. If the request stays, you can print the page in a headless browser instead of maintaining a second template. Puppeteer and Playwright both expose a page.pdf() call for this.
- Costs: more CSS to test, and a headless browser in your stack if you generate PDFs.
- Misses: backgrounds. Browsers drop background colors and images by default, one developer noted, which broke the checkerboards on their chess diagrams.
print-color-adjust: exactasks the browser to keep them, or draw them as SVG. Page counters remain hard, another commenter said.
Which level fits your site
| Site | Level | Why |
|---|---|---|
| Internal dashboard | Good | Rarely printed |
| Blog or docs | Better | Readers print long articles |
| Invoices, tickets, resumes | Best | They end up as PDFs anyway |
| Long technical docs with code | Best | Code blocks split without break rules |
The case against bothering
Not everyone agrees this is worth the time. One developer put print support below on-screen UX and accessibility on a limited budget. Others called printing a waste of paper.
A reply in the discussion pushed back. Making pages basically printable from day one is cheap, and it widens your options for PDF generation later. I think the middle level is the sensible floor for any text-heavy site.
FAQ
How do I make a website printable with CSS?
Add a @media print block to your stylesheet. Hide navigation and other screen-only elements, set body text to about 12pt, and make links black. Then add break-inside: avoid on code blocks, figures and tables.
Why do background colors disappear when I print a web page?
Browsers skip background colors and images when printing by default to save ink. Set print-color-adjust: exact on the elements that need them. Readers can also turn on “print backgrounds” in the print dialog.
How do I stop code blocks from breaking across pages?
Use break-inside: avoid on pre elements in your print stylesheet. A block taller than a page will still split, so keep long samples short or link to them.
Can I generate PDFs from my existing HTML pages?
Yes. Render the page in a headless browser and print it to PDF, for example with Puppeteer or Playwright. With a good print stylesheet, you don’t need a separate PDF template.
Should I show link URLs in print?
For articles and docs, yes. A link is useless on paper without its target. Use an ::after rule that prints the href, or move links into footnotes.
Is print CSS worth it for every site?
No. Dashboards and apps are rarely printed. Text-heavy pages, invoices, tickets and resumes benefit most.
Sources
- Article: Websites Should Be Printable by Brennen Puth.
- Discussion: https://news.ycombinator.com/item?id=50241664, for the points on PDF export, dropped backgrounds, missing print rules and the case against.