打印时应用样式

前端开发 2026-07-08

我有一个 @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>

在打印事件进行时(也就是在 beforeprintafterprint 之间),我期望 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章