window.print()可直接触发浏览器原生打印,弹出系统对话框,需DOM就绪且避免跨域/iframe调用;@media print控制样式,JS动态增删内容需手动还原;它不生成PDF,仅支持用户手动保存为PDF。

直接调用 window.print() 就能触发打印
浏览器原生支持,不需要额外库或服务端参与。执行后会弹出系统级打印对话框(含预览、选择打印机、页边距等),用户确认后才真正输出。
常见错误是把它写在页面加载完成前、或绑定在未渲染的按钮上,导致点击无反应;也有人误以为它能“自动打印不弹窗”,实际上所有现代浏览器都禁用静默打印(除非企业策略强制启用)。
- 推荐放在
<button onclick="window.print()">打印本页</button>里,确保 DOM 已就绪 - 避免在
iframe或跨域子页面中调用 —— 可能被拒绝或无响应 - 移动端 Safari 对
window.print()支持不稳定,部分 iOS 版本会忽略调用
用 @media print 控制打印样式
默认情况下,网页所有元素都会进打印预览,但导航栏、广告、背景图、浮动按钮这些通常不该出现。CSS 的 @media print 是唯一可靠方式,它只在打印上下文生效,不影响屏幕显示。
注意:很多开发者漏掉 display: none 的重置逻辑,或误用 visibility: hidden(它仍占布局空间,可能造成空白页)。
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 隐藏非内容区域:
@media print { .header, .sidebar, .ad-banner { display: none; } } - 强制显示关键文本(比如链接地址):
a[href]:after { content: " (" attr(href) ")"; } - 移除背景色和图片节省墨水:
@media print { * { background: transparent !important; color: #000 !important; } img { display: none; } }
打印前临时修改 DOM 再还原
有些内容需要“仅打印时存在”,比如页眉页脚、生成时间、水印文字,但又不能常驻在页面上干扰浏览。这时不能只靠 CSS 控制,得用 JS 动态插入再清理。
关键点在于:必须在 window.print() 调用前完成插入,且监听 afterprint 事件还原(虽然该事件兼容性差,建议用 setTimeout 延迟还原更稳妥)。
- 插入页脚示例:
const footer = document.createElement('div'); footer.className = 'print-only'; footer.textContent = '生成于 ' + new Date().toLocaleString(); document.body.appendChild(footer); window.print(); // 还原(不依赖 afterprint) setTimeout(() => { footer.remove(); }, 100); - 避免操作
document.write()或整个body.innerHTML替换 —— 会丢失事件绑定和状态 - 若页面含 Vue/React 组件,不要直接操作其内部 DOM;优先用组件级打印专用 slot 或 prop 控制显隐
PDF 导出不是打印,别混淆
window.print() 不生成 PDF 文件,只是唤起浏览器打印流程。用户手动选“保存为 PDF”才能得到文件 —— 这步完全由用户控制,前端无法跳过或预设文件名。
真要自动生成 PDF,得用 jsPDF + html2canvas 等方案,但它们本质是截图+合成,不保留语义结构、无法选中文本、分页不可控,和原生打印体验差距很大。
- 想加页眉页脚/页码/多页自动分栏?原生打印做不到,必须用 PDF 库,但代价是体积大、性能差、中文断行错乱风险高
- 银行/政务类系统常要求“打印即盖章效果”,这类需求实际依赖服务端 PDF 渲染(如 Puppeteer),前端纯 HTML 打印无法满足
- 记住:打印样式表和 PDF 导出是两条技术路径,混用容易两头不讨好
打印功能看着简单,但细节全在边界条件里:移动端兼容性、动态内容还原时机、CSS 选择器优先级冲突、以及最麻烦的 —— 用户永远会点“取消”然后回来问“为什么没打出来”。


















