When Print Stylesheets Break Blogs (and Your Sanity)
Setting Up a Print Stylesheet That Doesn’t Look Like a 1999 Fax
If you’ve ever hit “Print” on your own blog and watched it vomit out 13 pages of sidebar spam, congratulations: you’re a member of the club. I had a Chrome-broken-week last month where one client’s site spat out ten pages just for a sticky navbar alone. Not sticky in print, obviously—just dominant and immortal.
Start here: add a simple media="print"
stylesheet. If you’re using CSS-in-JS or some wild SSG setup, yes, you still need a dedicated print.css. Don’t rely on generic @media
chunks in your main layout file. Browser rules around media queries inside scoped or dynamic style blocks vary just enough to make things unpredictable.
@media print {
body {
background: none;
color: black;
}
nav, footer, aside {
display: none !important;
}
a::after {
content: " (" attr(href) ")";
}
}
Also: Always treat display: none
like a liability when used on body-level elements. Safari (even latest) randomly refuses to honor it when printing unless the element was visible on initial render. I debugged one case where a hidden div with an iframe pushed a blank first page.
Common Pitfalls with Page Breaks and Long Content
This one hits especially hard for recipe bloggers or tutorial writers. Anything longer than 4 pages will find a new and special way to split mid-code or mid-list… but here’s the twist: Chrome and Edge sometimes treat lists with display: list-item
like inline-blocks when rendered for print. No idea why. No workaround listed officially either.
The fix that worked here was setting page-break-inside: avoid
on ol
and ul
together with display: block
, even if it should’ve already inherited that. And, optionally, wrap each list in div.print-section
(yes, it’s gross) just to isolate the flow.
@media print {
ul, ol {
page-break-inside: avoid;
display: block;
}
}
Even then, Firefox may shove a horizontal rule into the middle of your list if inheritance is interrupted by DOM noise. Browser print engines still mostly act like they’re tethered to old printer drivers; they crash gracefully but unpredictably.
Handling AdSense Content in Print (Yes, You Should)
Fun fact: AdSense scripts are useless in print views. Another fun fact: if you don’t hide your ad containers, the whole layout warps because they leave behind weird space stubs. I went through this twice before I learned to flag all ad areas with both .adsbygoogle
and a [data-ad]
attribute just to be safe.
@media print {
.adsbygoogle,
[data-ad] {
display: none;
visibility: hidden;
}
}
Real catch: If your layout uses grids or flex areas where the ads are one column, removing the ad can cause column collapse depending how content is distributed. You’ll need to explicitly set width percentages or fallbacks (like min-height
) so the printed layout doesn’t look like a ransom note.
I once had a 3-column layout (main/content/sidebar) where removing the ad truncated the page down to 2/3 width for 8 printed pages. Still baffling.
Preserving Code Blocks When Printing Dev Blogs
Bloggers who include code samples (any syntax highlighting library, Prism, Highlight.js, etc.) often forget that the print view strips most styles unless those get re-applied deliberately. The syntax colors get dropped. Also, line numbers weirdly show up as printable ul
elements if you don’t namespace properly.
The fix that mostly works
- Force monospace font:
font-family: monospace !important;
- Set a soft background:
background: #f4f4f4;
but never pure black - Break on long words:
overflow-wrap: break-word
- Disable scroll wrappers:
max-height: none
in print - Always use
pre code
nesting to preserve spacing
Real-life moment: I had printed a 4-page blog post for a JS class once—looked great until one student told me the code blocks showed up completely blank in Safari. Turned out WebKit clipped anything wrapped in .overflow-auto
with max-height: 300px
. Not even white boxes. Just… gone.
Why Inline Styles Wreck Print More Than Anything Else
This is the one people miss. If your CMS outputs inline styles (looking at you, older WordPress Gutenberg block plugins), your print view gets tanked by over-specificity. Print media styles can’t override inline style="color: #ccc"
unless you override at the element level with !important
.
I spent half a day fighting a paragraph styled inline as <p style="color:#222;background-color:#eee">
where print correctly flipped text to black but preserved the background. Made it unreadable. Turns out the only solution was to use filter: grayscale(100%) brightness(1.1)
to tone it down in print. Felt hacky but it worked.
And oh, forget trying to wipe inline fonts. font-family
set inline sticks unless you reapply a universal reset or target deeply. Which means your blog post might look system-default for 95%—then Lucida Sans just randomly shows up for one blockquote.
Print-Specific Metadata: The Extra Stuff That’s Worth It
There’s actually a fair bit you can/should add to print versions of content that you don’t need on the browser view:
- Add a visible URL after links with
a::after
- Include document title via
title::before
- Stamp your domain in the footer with a basic
content
disclosure - Force visible page numbers per section with CSS counters and
@page
- Kinda undocumented: You can use
@page :first
to suppress headers on page 1 in some modern browsers
Power move: Create a simple print watermark with position: fixed
and opacity: 0.05
using custom branding or copyright. Chrome and Firefox respect it, Edge sometimes clips it unexpectedly when scaling to A4 though.
Unexpected Interaction with Dark Mode Overrides
This one’s a sleeper issue. I was using the prefers-color-scheme
query to style my blog’s dark/light themes. Turns out, in print contexts, some browsers (esp. older mobile Safari and Firefox) retain dark mode body styling in print unless background: #fff !important
is explicitly forced in the print block.
So yes, your printout may show up with dark gray or blue-tinted background and white text unless you aggressively reset it. Safari is especially bad about honoring non-force-overridden dark variables in print.
Even weirder: a Chrome Mobile print preview once used the dark-mode favicon rather than the light one—even though favicons don’t render on print—the behavior shifted header link colors downward anyway. Repeatable in Chrome 106+ only if the favicon was animated. Which feels fake. But alas, I saw it.
A Print CSS That Actually Worked (No Joke)
I finally got a setup that handled 90% of my headaches. Here’s the chunk that might actually help someone stumbling through this at 1:17am with coffee number five. This is the one that helped me sleep.
@media print {
body {
font: 12pt/1.4 Helvetica, Arial, sans-serif !important;
background: none !important;
color: black;
}
a::after {
content: " (" attr(href) ")";
font-size: 10pt;
}
nav, aside, footer, .ads, .no-print {
display: none !important;
}
h1, h2, h3, h4 {
page-break-after: avoid;
color: black;
}
pre, code {
page-break-inside: avoid;
white-space: pre-wrap;
background: #f4f4f4;
border: 1px solid #ccc;
}
}
I won’t pretend to understand why the white-space: pre-wrap
saved monospace layouts from clipping halfway through, but it did. That alone dodged an entire page-break collapse in multiple test prints.