Print Styles (@print)
Printing is a genuinely different medium: no hover states, no fixed viewport, a fixed page size instead of infinite scroll, and ink is expensive. A dedicated print stylesheet — scoped with the print media type — strips chrome, controls where pages break, and makes links useful on paper by printing the URL next to them.
@media print
@media print {
nav, aside, .site-footer, .no-print, video, .ad-slot {
display: none !important;
}
body {
color: #000;
background: #fff;
}
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.85em;
color: #555;
}
}@media print(see @media) only applies while printing or in print-preview — it never affects the on-screen experience.Hiding navigation, ads, and decorative chrome is almost always step one — none of it is useful once the page is on paper.
!importantis one of the few places it earns its keep: print overrides frequently need to beat deeply specific component styles you don't want to refactor just for print.
print.css file linked with media="print" works identically to an @media print block and lets the browser defer loading it until it's actually needed — either approach is fine; pick whichever fits your build setup.Printing link URLs
On screen a link's destination is implicit (click it, see where you land); on paper it's invisible unless you print it. The content: attr(href) trick above surfaces it, but exclude internal anchors and JavaScript links where it's noise rather than signal.
@media print {
a[href^="http"]:not([href*="yourdomain.com"])::after {
content: " (" attr(href) ")";
}
/* Skip on-page anchors and script hooks — nothing useful to print */
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
}Page breaks
The modern properties are break-before, break-after, and break-inside (the older page-break-* properties still work as aliases in every browser, so either is safe, but the newer names also apply to multi-column and fragmented contexts, not just print).
@media print {
h1, h2 {
break-after: avoid; /* keep a heading with the text that follows it */
}
table, figure, .card {
break-inside: avoid; /* don't split a table/figure mid-row */
}
.chapter {
break-before: page; /* force each chapter onto a fresh page */
}
}Value | Meaning |
|---|---|
| Default — break wherever the page naturally runs out |
| Prefer not to break here if possible |
| Always force a page break here |
| Force a break, landing the next content on a specific page side (for duplex printing) |
@page — margins and page boxes
@page configures the printed page box itself — margins, size, and (in supporting browsers) running headers/footers via named page-margin boxes.
@page {
margin: 2cm;
}
/* Different margins for the first page only */
@page :first {
margin-top: 4cm;
}
/* Landscape, for a wide report */
@page {
size: A4 landscape;
}@page selectors (:first, :left, :right) target page boxes, not DOM elements — you cannot select a page by class or ID, only by these fixed pseudo-classes.Orphans and widows
An orphan is a single line of a paragraph stranded alone at the bottom of a page; a widow is a single line stranded alone at the top of the next page. Both hurt readability in print, and both are controllable.
@media print {
p {
orphans: 3; /* at least 3 lines must stay at the bottom of a page */
widows: 3; /* at least 3 lines must start the next page */
}
}Print-friendly colors
Dark backgrounds with light text look fine on screen and burn through a full page of ink or print as solid black rectangles — flip to light background, dark text for print.
background-colorandbackground-imageare dropped by most browsers' default print settings unless the user explicitly enables "print background graphics" — never rely on a colored background alone to convey information in print.If a background genuinely must print (a branded letterhead strip, for example), pair it with
print-color-adjust: exact(formerly-webkit-print-color-adjust: exact), and accept that some users still won't see it if their OS print dialog forces backgrounds off.
Testing prints
Chrome/Edge DevTools: open the Rendering tab (Cmd/Ctrl+Shift+P → "Rendering") and set "Emulate CSS media type" to
print— this previews the print stylesheet live without opening the OS print dialog.Use the browser's actual Print Preview (Cmd/Ctrl+P) as the final check — some print-specific behavior (page breaks,
@pagemargins, header/footer injection) only shows accurately there.Test at more than one page size if your audience might print Letter or A4 — margins and break points can shift meaningfully between them.
Related pages: @media, Multi-Column Layout for break-inside in non-print contexts, and Accessible Animations for another "different medium" mindset with prefers-reduced-motion.