本文约 4,768 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:打印出来二十页,有用的只有三段
做技术博客的人多少遇到过这种反馈:读者把教程打印出来贴在工位,结果发现打印稿里夹着侧边栏推荐、相关文章卡片、评论框、深色背景整块黑底,一份 1500 字的文章打印了 9 页,其中 6 页是导航和广告。更糟的是打印稿里所有超链接都变成普通黑色文字,读者想按链接找原文根本找不到。
打印样式(print stylesheet)是被绝大多数商业主题忽略的一环。原因不难理解:它不影响任何线上指标,无法在 Google Analytics 里体现价值,所以几乎没有主题把它列入卖点。但对于教程站、文档站、外贸站的产品规格页,打印是真实存在的场景——客户会把规格参数打印给采购,读者会把步骤打印出来照着操作。把它做成「所见即所得的一页纸」,是低成本但感知很强的一件事。
原理分析:@media print 到底改变了什么
浏览器打印时切换的是媒体类型 print。此时有几条与屏幕完全不同的规则:
| 特性 | 屏幕(screen) | 打印(print) |
|---|---|---|
| 背景色/背景图 | 正常渲染 | 默认不打印(省墨设置) |
| 单位建议 | px / rem | pt / mm / cm |
| 分页 | 不存在 | 由 break-* 属性控制 |
| 绝对定位元素 | 正常 | 常被截断或跑到页外 |
| 白色文字 | 正常 | 白底上看不见 |
| 链接 | 有 hover / 下划线 | 全部失去交互,看不出是链接 |
其中最致命的两条是:深色主题在打印时会把深底丢掉、留下浅色文字,直接变成一片空白;以及链接失去可辨识性。@media print 的作用就是在打印这一刻把这两类问题覆盖掉。
加载方式上,WordPress 主题里有两种写法:单独一个 print.css 用 wp_enqueue_style() 注册时指定 media => 'print';或者直接写进主样式表的 @media print {} 块。前者的好处是可以被缓存策略单独处理,也便于子主题整份替换;后者少一个请求。这里用独立文件方案,因为它天然支持子主题覆盖。
保姆级实操
步骤 1:在主题里准备文件
在主题(或子主题)根目录建 print.css,与 style.css 平级。
步骤 2:只在打印媒体下加载
<?php
/**
* 加载打印样式,media 指定为 print,不影响屏幕渲染性能
*/
add_action( 'wp_enqueue_scripts', 'mimangfei_print_styles' );
function mimangfei_print_styles() {
wp_enqueue_style(
'mimangfei-print',
get_stylesheet_directory_uri() . '/print.css',
array(),
wp_get_theme()->get( 'Version' ),
'print'
);
}
wp_enqueue_style() 的第五个参数就是 media,传 'print' 后浏览器会把它标记为打印专用,屏幕渲染时不参与 CSSOM 阻塞,对首屏没有任何开销。
步骤 3:写 print.css 主体
@page {
size: A4;
margin: 16mm 14mm;
}
@media print {
/* 隐藏一切与正文无关的区域 */
.site-header .banner,
.site-navigation,
.widget-area,
.sidebar,
.comments-area,
.related-posts,
.post-navigation,
.site-footer,
.wp-block-buttons,
.sharedaddy,
.ad-slot,
.breadcrumb { display: none !important; }
/* 容器归零,避免残留外边距 */
body,
.site-content,
.entry-content {
margin: 0 !important;
padding: 0 !important;
width: auto !important;
max-width: none !important;
float: none !important;
}
/* 强制可读的前景色,杜绝白字白底 */
body, p, li, td, th, blockquote {
color: #000 !important;
background: transparent !important;
font-size: 11pt;
line-height: 1.5;
}
h1 { font-size: 20pt; }
h2 { font-size: 16pt; }
h3 { font-size: 13pt; }
/* 标题不被拆到上一页末尾 */
h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
img, table, pre, figure { break-inside: avoid; page-break-inside: avoid; }
p, li { orphans: 3; widows: 3; }
/* 图片自适应纸宽 */
img { max-width: 100% !important; height: auto !important; }
}
步骤 4:把链接地址打印出来
这是打印样式里最容易被忽略、也最有用的一条:
@media print {
/* 正文内的外部链接在后面附上真实地址 */
.entry-content a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 9pt;
color: #444;
word-break: break-all;
}
/* 站内锚点与图片链接不展开,避免刷屏 */
.entry-content a[href^="#"]::after,
.entry-content a[href*="wp-content/uploads"]::after {
content: none;
}
}
attr(href) 是 CSS2 就有的函数,兼容性极好,不需要任何 JS。第二条排除规则很重要,否则每张图片链接都会打印出一段冗长 URL。
步骤 5:加一段打印页脚
纯 CSS 无法拿到文章标题,需要服务端配合,用 wp_head 注入一个只在打印时显示的元素:
<?php
add_action( 'wp_head', 'mimangfei_print_footer' );
function mimangfei_print_footer() {
if ( ! is_singular( 'post' ) ) {
return;
}
$title = esc_html( get_the_title() );
$url = esc_url( get_permalink() );
echo '<div class="print-only-footer">' . $title . ' — ' . $url . '</div>';
}
.print-only-footer { display: none; }
@media print {
.print-only-footer {
display: block;
position: fixed;
bottom: 0;
left: 0;
right: 0;
font-size: 9pt;
color: #666;
border-top: 1px solid #ccc;
padding-top: 4pt;
}
}
position: fixed 在分页打印时行为因浏览器而异,Chrome 会只在第一页底部渲染一次,这已经足够起到溯源作用。
步骤 6:验证
Chrome 打开任意文章页 → Ctrl+P,在打印预览里逐项检查:页数是否落在合理区间、有没有黑块、链接是否带地址、表格是否被拦腰截断。Firefox 的打印预览对 break-inside 支持更严格,建议两个都过一遍。
常见踩坑
- 只在
@media print里写display:none,忘了重置宽度:侧边栏消失后主内容仍带着max-width: 720px,右半张纸留白。必须同时把width/max-width归零。 - 深色主题打印出黑块:即便设了
background: transparent,若主题用filter: invert()或mix-blend-mode处理深色模式,打印时依然会出问题,需要在打印块里显式filter: none。 !important加得不够:主题样式表优先级可能更高,尤其是用:where()之外的块样式。打印样式要靠!important兜底。- 背景图二维码消失:打印时背景图默认不输出,不要把二维码做成
background-image,用<img>标签。 - 案例: 某文档站给
pre代码块加了overflow-x: auto,打印时横向溢出的代码被直接裁掉右半行,读者照着抄命令全是错的。修法是打印态下改为overflow-x: visible; white-space: pre-wrap; word-break: break-all;,宁可换行也不能裁切。 - 强制分页用
page-break-before: always写在每个h2上:会让一页只放一个小节,纸张浪费严重。正确做法是只在h1或明确的章节容器上用。 - 忘了
print媒体参数:wp_enqueue_style()不传第五个参数时默认all,打印样式会参与屏幕渲染,其中的!important可能污染前台。
总结
一份合格的打印样式,判断标准就三条:打印页数与正文长度相称(1500 字文章应落在 2–3 页)、页面上没有任何深色块或空白区域、所有外部链接都带有可见地址。做到这三条,打印稿就能直接用。
实施成本很低,一个 60 行左右的 print.css 加 10 行 PHP 注册代码即可覆盖绝大多数主题。优先级上,教程/文档/产品规格类站点值得做,纯资讯站可以只做隐藏侧边栏和链接展开两项最小改动。若你还想顺带优化打印时的图片体积,可以参考 主题加载的资源请求数精简清单;打印样式本身不参与屏幕渲染,因此与 WordPress主题性能优化的度量方式 里的首屏指标互不干扰。
