data-print="true"比class="no-print"更可靠,因其避免样式冲突且需精确匹配;@media print必须独立加载;表格跨页需thead与page-break-inside配合;打印前须清理干扰DOM。

data-print 属性比 class="no-print" 更可靠
用 class="no-print" 隐藏非打印内容容易和框架样式冲突(比如 Ant Design 的 .ant-btn 里可能已有同名 class),导致该隐藏的没藏掉、不该藏的被藏了。而 data-print="true" 是显式声明“这是我要打的内容”,JS 和 CSS 都能精准识别。
常见错误:写成 [data-print],结果广告脚本或第三方 SDK 也加了这个属性,整个页面全进打印流。
- 必须写全
[data-print="true"],不接受模糊匹配 - 只在最外层容器加,别给每个
<p>或<div>都加——增加 JS 提取成本,也易漏删 - 示例写法:
<div data-print="true"><h2>发票明细</h2><table>...</table></div>
@media print 必须独立加载,不能混在 screen.css 里
把 @media print 塞进主样式表末尾,大概率失效——前面的 .container { width: 1200px; } 会覆盖它;用 <link rel="stylesheet" media="screen" href="style.css">,浏览器压根不加载 @media print 规则。
正确做法是单独建 print.css,并用 media="print" 显式声明:
立即学习“前端免费学习笔记(深入)”;
<link rel="stylesheet" href="print.css" media="print">
注意:media 值大小写敏感,写成 PRINT 或 Media="print"(首字母大写)都不生效。
- 不要在
print.css里写* { margin: 0; }——会干掉<table>默认边距,造成边框塌陷 - 移动端 Safari 不支持
window.print(),得提前检测:if (!window.print) { /* fallback 提示或导出 PDF */ }
表格跨页断裂?thead + page-break-inside 缺一不可
只给 <table> 加 page-break-inside: avoid 没用。浏览器仍可能把 <thead> 留在第一页,<tbody> 第二页开头只剩半行。
关键组合是两行 CSS 同时生效:
thead { display: table-header-group; }
tr { page-break-inside: avoid; }display: table-header-group 告诉浏览器“每页都要重绘这个头”,page-break-inside: avoid 阻止单行被切开。
- IE 不支持
page-break-inside,需 fallback:tr { display: table-row; } -
table { width: 100% !important; border-collapse: collapse; }强制撑满纸张,禁用max-width或固定px值 - 调试时用 Chrome DevTools → Rendering → Emulate CSS media: print,比反复 Ctrl+P 快得多
window.print() 前必须手动清理干扰 DOM
浏览器不会自动忽略 visibility: hidden 的按钮、position: fixed 的页脚水印、或未关闭的 modal。它们虽不可见,却参与分页计算,轻则多出空白页,重则内容错位。
推荐做法不是靠 CSS 隐藏,而是临时移除:
function printPage() {
const printArea = document.querySelector('[data-print="true"]');
const originalHTML = printArea.innerHTML;
Array.from(printArea.parentNode.children)
.filter(el => !el.hasAttribute('data-print'))
.forEach(el => el.remove());
window.print();
setTimeout(() => { printArea.innerHTML = originalHTML; }, 100);
}window.print() 是同步阻塞调用,但没有可靠回调,所以还原 DOM 只能靠 setTimeout,且延迟不能太短(0 不够,100 是经验值)。
- 别用
document.body.innerHTML = printContent替换整页——会丢失事件监听器、破坏 Vue/React 组件状态 - 动态生成的广告位、tooltip、loading 遮罩,必须在
printPage()开头统一remove(),不能只依赖 CSS
真正落地的打印配置,难点不在写多少 CSS,而在 DOM 干净度、样式隔离粒度、以及浏览器对 page-break 的实际解析差异——这些地方稍不注意,就从“能打出来”变成“打出来没法用”。



















