打印时应用样式
我有一个 @media print 样式表(在页面内联)会覆盖打印时的颜色。
我有一个用于渲染图表的组件,需要在打印时重新渲染——否则处于深色模式的用户在白色页面上会看到白色文本。
因此在 beforeprint 事件上,我会重新渲染所有图表,使之应用当前的打印样式。
当我使用 CTRL+P 进行打印时这方法是可行的,但用户需要一个按钮,而当我调用 window.print() 时,beforeprint 并不总是触发,父组件上的 getComputedStyle(this) 会报告 @media screen 样式,而不是 print 样式。
这是一个基本的重现,但在Stack Overflow的代码片段中并不能稳定地工作:
window.addEventListener(
'beforeprint',
() => console.log('Printing...', window.matchMedia('print')))
document.querySelector('button').addEventListener(
'click',
() => print());
#demo {
border: 4px solid red;
padding: 2em;
}
@media print {
#demo {
border: 8px solid blue;
}
}
<div id="demo">text</div>
<button>print</button>
在打印事件进行时(也就是在 beforeprint 与 afterprint 之间),我期望 window.matchMedia('print') 为true,但实际是false?
打印应该应用 @media print 查询,将 <div> 的边框改为蓝色——这有时能起效,有时不能,我也不知道为什么。
- 有没有办法把页面强制切换到
@media print模式? - 有没有办法检查
window.matchMedia('print')或等待它为真? - 能否以某种特定方式调用
window.print(),以确保应用我的@media print样式?
解决方案
如何检测媒体变化
matchMedia change事件 可用于检测媒体变化:
window.matchMedia('print').addEventListener('change', (e) => {
console.log(e.matches);
})
与 beforeprint事件 不同,这允许用户在打印样式应用后再渲染图表。另一个优点是浏览器在渲染时会暂停打印对话框。如果这是一个较长的过程,对话框会显示一条信息,例如“正在准备预览”(在Chrome、Edge和 Firefox上测试过)。
打印事件测试
const printMedia = window.matchMedia('print');
printMedia.addEventListener('change', handler);
document.querySelector('button').addEventListener('click', (e) => {
handler(e);
print()
});
addEventListener('beforeprint', handler);
addEventListener('afterprint', handler);
function handler(e) {
let color = getComputedStyle(chart).borderColor;
console.log(`${e.timeStamp.toFixed()}: ${e.type}, ${printMedia.matches}, ${color}`);
if (printMedia.matches) {
chart.textContent = 'Print Chart';
}
else {
chart.textContent = 'Screen Chart';
}
}
html {
font-family: sans-serif;
}
#chart {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 75px;
background: black;
color: white;
border: 4px solid red;
padding: 2em;
}
@media print {
#chart {
background: white;
color: black;
border: 8px solid blue;
}
button {
display: none;
}
}
<button>Print</button>
<div id="chart">Screen Chart</div>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。