根本原因是主流打印引擎不解析CSS图像值,仅支持可栅格化资源;必须用canvas绘制渐变转base64图片并设为background-image,且@media print中需同时声明-webkit-print-color-adjust: exact和color-adjust: exact,导出前确保图片加载完成并启用printBackground:true。

为什么CSS渐变在打印时完全不显示
根本原因不是浏览器不支持 linear-gradient,而是所有主流打印引擎(Chrome、Edge、Firefox 的 window.print(),以及 wkhtmltopdf、Puppeteer 等导出工具)都不解析 CSS 图像值。它们只处理可栅格化的资源,比如 PNG、JPEG 或纯色。一旦遇到 background: linear-gradient(...),直接跳过渲染——连 fallback 都不给。
用 canvas 生成 PNG 替代渐变背景
这是目前唯一能在纯前端、无服务端依赖下稳定生效的方案。核心是把渐变“画出来”,转成 base64 图片再塞回 background-image:
- 创建
<canvas></canvas>,尺寸必须匹配目标元素的打印宽高(例如按钮为160px × 35px) - 用
ctx.createLinearGradient()定义方向,addColorStop()添加色标 - 调用
ctx.fillRect()填满画布,再用canvas.toDataURL('image/png')生成 URI - 赋值给元素的
style.backgroundImage,而非通过 CSS 类动态写入
示例关键代码:
const canvas = document.createElement('canvas');
canvas.width = 160;
canvas.height = 35;
const ctx = canvas.getContext('2d');
const grad = ctx.createLinearGradient(0, 0, 160, 0);
grad.addColorStop(0, '#e68865');
grad.addColorStop(1, '#ea6731');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, 160, 35);
document.querySelector('.join').style.backgroundImage = `url(${canvas.toDataURL('image/png')})`;
@media print 里仍需保留 color-adjust 声明
即使用了 canvas 图片,background-image 在打印时仍可能被浏览器默认禁用。必须在 @media print 中对具体元素显式启用:
-
-webkit-print-color-adjust: exact和print-color-adjust: exact必须同时存在,且写在该元素的打印规则内 - 不能只挂在
body上,得作用于实际使用图片背景的类,比如.join - 避免用
rgba()或透明底色做 canvas 绘制——打印机不处理 alpha,结果可能是白块或灰块
导出 PDF 前必须确保图片已加载完成
很多 PDF 导出失败,不是因为 canvas 没画,而是截图时机早于图片加载。常见陷阱:
- Puppeteer 必须设置
printOptions: { printBackground: true },否则连background-image都清空 - Electron 或 html2canvas 截图前,加
await new Promise(r => setTimeout(r, 16))让微任务队列清空,确保 DOM 已更新 - Webpack/Vite 构建时,CSS 压缩器可能移除
background-image声明,需在相关样式上加/*! autoprefixer: off */注释保护
真正麻烦的不是怎么画渐变,而是怎么让那张 PNG 在导出那一帧刚好就位——它既不能太早(DOM 还没改),也不能太晚(截图已完成)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











