print-css

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Print CSS

打印样式表(Print CSS)

You are a print stylesheet specialist. You write
@media print
styles that make web pages look intentional on paper -- not like someone hit Cmd+P on a web page.
你是一位打印样式表专家。你编写的
@media print
样式能让网页在纸上呈现出精心设计的效果——而不是像直接按下Cmd+P打印网页那样杂乱。

When to Use This Skill

何时使用此技能

  • User asks to "make this printable" or "add print styles"
  • Building a page that will be printed (invitations, tickets, reports, invoices)
  • Creating a "Save as PDF" version of a web page
  • Fixing broken print layouts
  • 用户要求“让页面可打印”或“添加打印样式”
  • 构建需要打印的页面(邀请函、票据、报告、发票)
  • 创建网页的“另存为PDF”版本
  • 修复损坏的打印布局

Print Stylesheet Skeleton

打印样式表骨架

Every print stylesheet follows this structure, in order:
css
@media print {
  /* 1. Page setup */
  @page { size: letter; margin: 0.5in 0.6in; }

  /* 2. Force color reproduction */
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  /* 3. Base typography */
  body {
    background: white !important;
    color: #1a1a1a !important;
    font-size: 10.5pt;
    line-height: 1.6;
  }

  /* 4. Kill web-only elements */
  nav, .no-print, footer, .cookie-banner { display: none !important; }

  /* 5. Kill animations */
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }

  /* 6. Flatten layouts */
  /* ... framework-specific resets ... */

  /* 7. Page break control */
  h1, h2, h3 { page-break-after: avoid; break-after: avoid-page; }
  tr, img, blockquote { page-break-inside: avoid; break-inside: avoid-page; }
  p { orphans: 3; widows: 3; }

  /* 8. Images */
  img { max-width: 100%; max-height: 3in; }

  /* 9. Links */
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
  a[href^="#"]::after { content: ""; }

  /* 10. Tables */
  thead { display: table-header-group; }
  tfoot { display: table-footer-group; }
}

每个打印样式表都遵循以下结构顺序:
css
@media print {
  /* 1. Page setup */
  @page { size: letter; margin: 0.5in 0.6in; }

  /* 2. Force color reproduction */
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  /* 3. Base typography */
  body {
    background: white !important;
    color: #1a1a1a !important;
    font-size: 10.5pt;
    line-height: 1.6;
  }

  /* 4. Kill web-only elements */
  nav, .no-print, footer, .cookie-banner { display: none !important; }

  /* 5. Kill animations */
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }

  /* 6. Flatten layouts */
  /* ... framework-specific resets ... */

  /* 7. Page break control */
  h1, h2, h3 { page-break-after: avoid; break-after: avoid-page; }
  tr, img, blockquote { page-break-inside: avoid; break-inside: avoid-page; }
  p { orphans: 3; widows: 3; }

  /* 8. Images */
  img { max-width: 100%; max-height: 3in; }

  /* 9. Links */
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
  a[href^="#"]::after { content: ""; }

  /* 10. Tables */
  thead { display: table-header-group; }
  tfoot { display: table-footer-group; }
}

@page Rules

@page 规则

css
@page {
  size: letter;            /* or: A4, 210mm 297mm, landscape */
  margin: 0.5in 0.6in;    /* top/bottom  left/right */
}

@page :first {
  margin-top: 1in;        /* extra space for cover page */
}
Available sizes:
letter
(8.5x11in),
A4
(210x297mm),
A3
,
A5
,
legal
, or explicit dimensions.
Gotchas:
  • @page margin support is limited across browsers. Use padding on body/wrapper as fallback.
  • DevTools print emulation does not show @page effects. Must check actual print preview (Cmd+P).
  • Cannot set background-color at the page level reliably.

css
@page {
  size: letter;            /* or: A4, 210mm 297mm, landscape */
  margin: 0.5in 0.6in;    /* top/bottom  left/right */
}

@page :first {
  margin-top: 1in;        /* extra space for cover page */
}
可用尺寸:
letter
(8.5×11英寸)、
A4
(210×297毫米)、
A3
A5
legal
,或自定义尺寸。
注意事项:
  • 不同浏览器对@page边距的支持有限。可在body或容器上使用padding作为备选方案。
  • DevTools的打印模拟不会显示@page的效果,必须查看实际打印预览(Cmd+P)。
  • 无法在页面级别可靠地设置background-color。

Page Break Control

分页控制

Use both legacy and modern properties for maximum browser support:
css
/* Prevent breaking inside an element */
.card, tr, figure {
  page-break-inside: avoid;
  break-inside: avoid-page;
}

/* Force a break before a section */
.chapter {
  page-break-before: always;
  break-before: page;
}

/* Prevent a break right after a heading */
h1, h2, h3 {
  page-break-after: avoid;
  break-after: avoid-page;
}
同时使用旧版和新版属性以获得最佳浏览器兼容性:
css
/* Prevent breaking inside an element */
.card, tr, figure {
  page-break-inside: avoid;
  break-inside: avoid-page;
}

/* Force a break before a section */
.chapter {
  page-break-before: always;
  break-before: page;
}

/* Prevent a break right after a heading */
h1, h2, h3 {
  page-break-after: avoid;
  break-after: avoid-page;
}

Orphans and Widows

孤行控制(Orphans and Widows)

Prevent stranded lines at page boundaries:
css
p {
  orphans: 3;   /* minimum lines at bottom of page */
  widows: 3;    /* minimum lines at top of next page */
}
Gotchas:
  • page-break-inside: avoid
    does not work reliably on flex or grid containers. Switch to
    display: block
    in print.
  • Overusing
    break-inside: avoid
    can push content to the next page unpredictably.
  • Test with actual content -- short paragraphs behave differently from long ones.

防止页面边界出现孤立的单行:
css
p {
  orphans: 3;   /* 页面底部最少保留的行数 */
  widows: 3;    /* 下一页顶部最少保留的行数 */
}
注意事项:
  • page-break-inside: avoid
    在flex或grid容器上无法可靠工作。打印时需切换为
    display: block
  • 过度使用
    break-inside: avoid
    可能导致内容意外被推到下一页。
  • 需使用实际内容测试——短段落和长段落的表现不同。

Visibility

可见性控制

Elements to always hide in print

打印时需隐藏的元素

css
@media print {
  nav,
  .sidebar,
  .cookie-banner,
  .social-share,
  .comments,
  .ads,
  .chat-widget,
  .search-bar,
  .no-print {
    display: none !important;
  }
}
css
@media print {
  nav,
  .sidebar,
  .cookie-banner,
  .social-share,
  .comments,
  .ads,
  .chat-widget,
  .search-bar,
  .no-print {
    display: none !important;
  }
}

Print-only elements

仅打印元素

css
.print-only {
  display: none;  /* hidden on screen */
}

@media print {
  .print-only {
    display: block;  /* visible on paper */
  }
}
Use
display: none !important
(not
visibility: hidden
) -- visibility preserves layout space and wastes paper.

css
.print-only {
  display: none;  /* 屏幕上隐藏 */
}

@media print {
  .print-only {
    display: block;  /* 打印时显示 */
  }
}
使用
display: none !important
(而非
visibility: hidden
)——visibility会保留布局空间,造成纸张浪费。

Colors and Backgrounds

色彩与背景

print-color-adjust

print-color-adjust

Controls whether the browser can optimize colors for print:
css
* {
  -webkit-print-color-adjust: exact !important;  /* Safari/older Chrome */
  print-color-adjust: exact !important;           /* standard */
}
  • exact
    -- preserves declared colors (even if ink-heavy)
  • economy
    (default) -- browser may strip backgrounds, adjust colors
控制浏览器是否可以优化打印颜色:
css
* {
  -webkit-print-color-adjust: exact !important;  /* Safari/旧版Chrome */
  print-color-adjust: exact !important;           /* 标准语法 */
}
  • exact
    ——保留声明的颜色(即使墨水消耗量大)
  • economy
    (默认)——浏览器可能会去除背景、调整颜色

Color remapping for print

打印颜色重映射

Remap web colors to print-friendly equivalents:
css
@media print {
  body {
    background: white !important;
    color: #1a1a1a !important;
  }

  /* Vibrant accent becomes muted for paper */
  .text-coral { color: #A03030 !important; }

  /* Dark backgrounds become white with borders */
  .dark-card {
    background: white !important;
    border: 1px solid #ccc !important;
  }
}
Rule of thumb: If it's readable on white paper at arm's length, it works.

将网页颜色重新映射为适合打印的等效颜色:
css
@media print {
  body {
    background: white !important;
    color: #1a1a1a !important;
  }

  /* 鲜艳的强调色转为适合纸张的柔和色调 */
  .text-coral { color: #A03030 !important; }

  /* 深色背景转为白色并添加边框 */
  .dark-card {
    background: white !important;
    border: 1px solid #ccc !important;
  }
}
经验法则: 在白纸上手臂长度距离能清晰阅读,即为有效。

Typography

排版

Use points, not pixels

使用磅值(points)而非像素

Points render consistently across browsers and printers:
css
@media print {
  body {
    font-size: 10.5pt;
    line-height: 1.6;
  }
  h1 { font-size: 24pt; }
  h2 { font-size: 18pt; }
  h3 { font-size: 14pt; }
  code { font-size: 9pt; }
}
磅值在不同浏览器和打印机上的渲染效果一致:
css
@media print {
  body {
    font-size: 10.5pt;
    line-height: 1.6;
  }
  h1 { font-size: 24pt; }
  h2 { font-size: 18pt; }
  h3 { font-size: 14pt; }
  code { font-size: 9pt; }
}

Font stack for print

打印字体栈

Serif fonts are more readable on paper:
css
@media print {
  body { font-family: Georgia, 'Times New Roman', serif; }
  code, pre { font-family: 'Courier New', monospace; }
}
Gotchas:
  • Custom web fonts may not load in print. Always have serif/sans-serif fallbacks.
  • Remove light font weights (300, 200). Paper doesn't render thin strokes well.
  • Remove text-shadow. It doesn't translate to print.
  • Minimum legible body text: 9pt. Prefer 10-11pt.

衬线字体在纸张上更易阅读:
css
@media print {
  body { font-family: Georgia, 'Times New Roman', serif; }
  code, pre { font-family: 'Courier New', monospace; }
}
注意事项:
  • 自定义网页字体可能无法在打印中加载。务必提供衬线/无衬线备选字体。
  • 移除轻量级字重(300、200)。纸张无法清晰呈现细线条。
  • 移除文字阴影(text-shadow),它无法在打印中呈现。
  • 最小可阅读正文字体:9pt。优先选择10-11pt。

Images

图片

css
@media print {
  img {
    max-width: 100%;
    max-height: 3in;      /* prevent full-page images */
  }

  /* Hide decorative images */
  .hero-image,
  .background-image,
  .decorative {
    display: none !important;
  }

  /* Remove gradient overlays that hide content */
  [class*="bg-gradient"][class*="absolute"] {
    display: none !important;
  }
}
Gotchas:
  • Background images don't print by default. Use
    print-color-adjust: exact
    or move content to
    <img>
    tags.
  • Responsive images with
    srcset
    may not load correctly in print preview.
  • High-resolution images slow down PDF generation significantly.

css
@media print {
  img {
    max-width: 100%;
    max-height: 3in;      /* 防止图片占满整页 */
  }

  /* 隐藏装饰性图片 */
  .hero-image,
  .background-image,
  .decorative {
    display: none !important;
  }

  /* 移除遮挡内容的渐变覆盖层 */
  [class*="bg-gradient"][class*="absolute"] {
    display: none !important;
  }
}
注意事项:
  • 背景图片默认不会打印。使用
    print-color-adjust: exact
    或将内容移至
    <img>
    标签。
  • 使用
    srcset
    的响应式图片在打印预览中可能无法正确加载。
  • 高分辨率图片会显著减慢PDF生成速度。

Links

链接

Show URLs on printed links

在打印的链接后显示URL

css
@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
    color: #666;
  }

  /* Don't show URLs on anchor links */
  a[href^="#"]::after { content: ""; }

  /* Don't show URLs on links that already describe their destination */
  a.no-print-url::after { content: ""; }
}
Gotcha:
attr(href)
shows the full URL, which can be very long. Consider truncating with
max-width
and
overflow: hidden
on the ::after pseudo-element, or use custom content for known links.

css
@media print {
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
    color: #666;
  }

  /* 锚点链接不显示URL */
  a[href^="#"]::after { content: ""; }

  /* 已描述目标的链接不显示URL */
  a.no-print-url::after { content: ""; }
}
注意事项:
attr(href)
会显示完整URL,可能非常长。可以考虑在::after伪元素上使用
max-width
overflow: hidden
来截断,或为已知链接使用自定义内容。

Tables

表格

css
@media print {
  /* Repeat header on each page */
  thead { display: table-header-group; }
  tfoot { display: table-footer-group; }

  /* Prevent row splitting */
  tr {
    page-break-inside: avoid;
    break-inside: avoid-page;
  }

  /* Ensure borders print */
  table { border-collapse: collapse; width: 100%; }
  th, td {
    border: 1px solid #000;
    padding: 4pt 6pt;
  }
}

css
@media print {
  /* 每页重复表头 */
  thead { display: table-header-group; }
  tfoot { display: table-footer-group; }

  /* 防止行被拆分 */
  tr {
    page-break-inside: avoid;
    break-inside: avoid-page;
  }

  /* 确保边框可打印 */
  table { border-collapse: collapse; width: 100%; }
  th, td {
    border: 1px solid #000;
    padding: 4pt 6pt;
  }
}

Framework Gotchas

框架注意事项

Next.js

Next.js

next/image with
fill
breaks in print:
css
@media print {
  /* next/image fill uses absolute positioning -- force to static */
  [data-nimg="fill"],
  img[style*="position: absolute"] {
    position: static !important;
    width: 100% !important;
    height: auto !important;
  }

  /* Fix fill containers */
  [style*="position: relative"] {
    position: relative !important;
    overflow: visible !important;
  }
}
Where to put print styles: Use
@media print
in
globals.css
, not component-scoped styles. Print styles need global scope to override everything.
使用
fill
的next/image在打印中失效:
css
@media print {
  /* next/image的fill使用绝对定位——强制改为静态定位 */
  [data-nimg="fill"],
  img[style*="position: absolute"] {
    position: static !important;
    width: 100% !important;
    height: auto !important;
  }

  /* 修复fill容器 */
  [style*="position: relative"] {
    position: relative !important;
    overflow: visible !important;
  }
}
打印样式的放置位置:
globals.css
中使用
@media print
,而非组件作用域样式。打印样式需要全局作用域才能覆盖所有样式。
相关讨论: vercel/next.js#23039

React / CSS-in-JS

React / CSS-in-JS

  • Print media queries must be included in component styles or a global stylesheet.
  • Styled-components and Emotion support
    @media print
    blocks normally.
  • Dynamic class names work fine -- print styles override by specificity.
  • 打印媒体查询必须包含在组件样式或全局样式表中。
  • Styled-components和Emotion正常支持
    @media print
    块。
  • 动态类名可以正常工作——打印样式通过优先级覆盖原有样式。

Tailwind CSS

Tailwind CSS

css
@media print {
  /* Kill viewport height constraints */
  .min-h-screen, .min-h-svh, .h-screen { min-height: auto !important; height: auto !important; }

  /* Dark mode on paper = unreadable */
  .dark { background: white !important; color: #1a1a1a !important; }

  /* Opacity renders poorly on paper */
  [class*="opacity-"] { opacity: 1 !important; }

  /* Fixed elements don't print */
  .fixed { position: static !important; }

  /* Overflow hidden clips content at page breaks */
  .overflow-hidden { overflow: visible !important; }
}
css
@media print {
  /* 移除视口高度限制 */
  .min-h-screen, .min-h-svh, .h-screen { min-height: auto !important; height: auto !important; }

  /* 纸张上的暗色模式无法阅读 */
  .dark { background: white !important; color: #1a1a1a !important; }

  /* 透明度在纸张上渲染效果差 */
  [class*="opacity-"] { opacity: 1 !important; }

  /* 固定定位元素无法打印 */
  .fixed { position: static !important; }

  /* 溢出隐藏会在分页处裁剪内容 */
  .overflow-hidden { overflow: visible !important; }
}

Flexbox and Grid

Flexbox 和 Grid

Flex and grid containers do not handle page breaks correctly. Flatten them:
css
@media print {
  .flex, .grid { display: block !important; }

  /* Or selectively: keep horizontal flex but allow breaking */
  .flex-col { display: block !important; }
}
Exception: Short flex rows (nav items, button groups) can remain flex if they fit on one line and you use
page-break-inside: avoid
.

Flex和Grid容器无法正确处理分页。需将其扁平化:
css
@media print {
  .flex, .grid { display: block !important; }

  /* 或选择性处理:保留水平flex但允许分页 */
  .flex-col { display: block !important; }
}
例外情况: 短flex行(导航项、按钮组)如果能在一行显示,且使用
page-break-inside: avoid
,则可以保持flex布局。

Testing

测试

DevTools emulation (quick iteration)

DevTools模拟(快速迭代)

  1. Open DevTools (F12)
  2. Three-dot menu -> More tools -> Rendering
  3. "Emulate CSS media type" -> print
  4. Styles update in real-time
Limitations: Does not show page breaks, @page rules, or PDF headers/footers.
  1. 打开DevTools(F12)
  2. 三点菜单 -> 更多工具 -> 渲染
  3. “模拟CSS媒体类型” -> print
  4. 样式实时更新
局限性: 不显示分页、@page规则或PDF页眉/页脚。

Actual print preview (final check)

实际打印预览(最终检查)

  1. Cmd+P (Mac) / Ctrl+P (Windows)
  2. Check "Background graphics" to see colors/images
  3. Review page breaks, margins, and layout
  1. Cmd+P(Mac)/ Ctrl+P(Windows)
  2. 勾选“背景图形”以查看颜色/图片
  3. 检查分页、边距和布局

Checklist

检查清单

Before declaring print styles complete:
  • Web-only elements (nav, ads, widgets) are hidden
  • Page breaks don't split mid-card, mid-table-row, or mid-image
  • No orphaned single lines at top/bottom of pages
  • All text is legible (minimum 9pt, dark on white)
  • Images don't overflow onto the next page
  • Links show URLs (or are clearly styled as text)
  • Table headers repeat on each page
  • Backgrounds are either hidden or forced with print-color-adjust
  • No animations or transitions remain
  • Flexbox/grid layouts don't cause blank pages
  • min-height: 100vh constraints are removed
  • Fixed positioning is converted to static
  • Tested in actual print preview, not just DevTools emulation

在完成打印样式前需确认:
  • 仅网页元素(导航、广告、小部件)已隐藏
  • 分页不会在卡片、表格行或图片中间拆分
  • 页面顶部/底部没有孤立的单行
  • 所有文本清晰可读(最小9pt,白底深色字)
  • 图片不会溢出到下一页
  • 链接显示URL(或清晰地设置为文本样式)
  • 表格表头在每页重复显示
  • 背景已隐藏或通过print-color-adjust强制显示
  • 没有残留的动画或过渡效果
  • Flexbox/Grid布局不会导致空白页
  • 已移除min-height: 100vh限制
  • 固定定位已转为静态定位
  • 已在实际打印预览中测试,而非仅DevTools模拟

Agentic Workflow & Vibe Coding

智能工作流与氛围编码

  • Iterative Styling: Do not expect perfect print layouts on the first try, as print rendering engines are finicky. Draft a V1 stylesheet, preview the result, isolate specific breaks or visibility issues, adjust exactly ONE CSS rule at a time, and re-test until the layout is solid.
  • Vibe Coding: Commit your working CSS changes locally before tackling complex grid/flexbox flattening or cross-browser print quirks.
  • 迭代式样式编写: 不要期望第一次就能得到完美的打印布局,因为打印渲染引擎非常挑剔。先编写V1版本的样式表,预览结果,定位特定的分页或可见性问题,每次只调整一个CSS规则,重新测试直到布局稳定。
  • 氛围编码: 在处理复杂的grid/flexbox扁平化或跨浏览器打印 quirks之前,先在本地提交有效的CSS更改。

Utility Classes

工具类

Add these to your project for print control:
css
.no-print { }              /* hidden in print via @media print */
.print-only { display: none; }  /* hidden on screen, shown in print */
.print-break-before { }    /* page break before this element */
.print-break-after { }     /* page break after this element */
.no-print-url { }          /* suppress URL display on this link */

@media print {
  .no-print { display: none !important; }
  .print-only { display: block !important; }
  .print-break-before { page-break-before: always !important; break-before: page !important; }
  .print-break-after { page-break-after: always !important; break-after: page !important; }
}
将以下工具类添加到项目中以控制打印:
css
.no-print { }              /* 通过@media print在打印中隐藏 */
.print-only { display: none; }  /* 屏幕上隐藏,打印时显示 */
.print-break-before { }    /* 在此元素前分页 */
.print-break-after { }     /* 在此元素后分页 */
.no-print-url { }          /* 隐藏此链接的URL显示 */

@media print {
  .no-print { display: none !important; }
  .print-only { display: block !important; }
  .print-break-before { page-break-before: always !important; break-before: page !important; }
  .print-break-after { page-break-after: always !important; break-after: page !important; }
}