CSSPrint Styles (@print)

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

CSS
@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.

  • !important is 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.

Tip
A separate 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.

CSS
@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).

CSS
@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

auto

Default — break wherever the page naturally runs out

avoid

Prefer not to break here if possible

page

Always force a page break here

left / right

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.

CSS
@page {
  margin: 2cm;
}

/* Different margins for the first page only */
@page :first {
  margin-top: 4cm;
}

/* Landscape, for a wide report */
@page {
  size: A4 landscape;
}
Note
@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.

CSS
@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-color and background-image are 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.

Warning
Never encode meaning purely in color for a page that might be printed on a monochrome printer — pair color with an icon, label, or border style as well.
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, @page margins, 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.