博客地址jsonz1993.github.io/2018/06/win…css
近日有个需求是作页面打印的,趁这个机会补一下比较冷门的浏览器打印知识。本文只讨论 Chrome、Safari、Firefox浏览器的状况。git
首先浏览器打印是一个很成熟的应用~ 至少是很早就已经有应用的功能,因此不会有什么兼容问题github
最简单的打印就是直接调用 window.print()
,固然用 document.execCommand('print')
也能够达到一样的效果。json
这时候在Safari和Chrome都会弹起打印预览的窗口,FireFox没有预览而是直接让你选择打印机,OSx下能够经过预览PDF来预览~浏览器
通常这种直接在网页上调用 print 的方法是没办法知足咱们的业务需求,好比说:app
那么有哪些方法能够帮助咱们改善打印的用户体验呢?dom
咱们能够在 link 上加上一个 media="print" 来标识这是打印机才会应用的样式表, 如:ide
<link href="/example.css" media="print" rel="stylesheet" />
复制代码
这样打印的时候,就会默认将该样式表应用到文档中布局
兼容性: IE9+ 其余主流浏览器都支持 当咱们要修改的样式没有那么多的时候,其实彻底不须要从新写个样式表,只要写上一个媒介查询也能够达到一样的效果,如:
h1 {
font-size: 14px;
}
@media print {
h1 {
font-size: 20px;
}
}
复制代码
有两个事件能够监听到到打印事件,一个是beforeprint
,一个是afterprint
,分别表示打印事件触发先后。 这个事件在 IE6 就已经支持了,不过一点都不惊讶~ 毕竟IE很早就支持不少接口调用,以前好像作过IE打开Excel的需求~ 兼容大概是 Firefox、IE全支持, Chrome63+支持, Safari暂不支持,算是一半一半吧。
window.addEventListener('beforeprint', ()=> {
document.body.innerHTML = '正在打印...';
});
window.addEventListener('afterprint', ()=> {
document.body.innerHTML = '打印完成...';
});
复制代码
若是你想要兼容Safari或许能够试一下 window.matchMedia
兼容是 IE10+,其余主流浏览器彻底没问题。
这个的用法稍微有点不同,首先建立一个MediaQueryList对象,再经过他监听变化,如:
const printMedia = window.matchMedia('print');
function printChange({ matches, }) {
document.body.innerHTML = matches? '正在打印...': '打印完成/取消';
}
printMedia.addListener(printChange);
复制代码
若是项目上用的是jq等,或者想简单粗暴的打印某个区域又不想从新写样式表啊,什么的。 最傻瓜版的方式就是直接用jq插件 jQuery.print
也能够本身写一个去处理,大概的思路是建立一个iframe,把要打印的dom和样式表都丢进去,再调用iframe的打印事件。 这里写一个简单的 demo
function printPartial(dom, { title= document.title,}= {}) {
if (!dom) return;
let copyDom = document.createElement('span');
const styleDom = document.querySelectorAll('style, link, meta');
const titleDom = document.createElement('title');
titleDom.innerText = title;
copyDom.appendChild(titleDom);
Array.from(styleDom).forEach(item=> {
copyDom.appendChild(item.cloneNode(true));
});
copyDom.appendChild(dom.cloneNode(true));
const htmlTemp = copyDom.innerHTML;
copyDom = null;
const iframeDom = document.createElement('iframe');
const attrObj = {
height: 0,
width: 0,
border: 0,
wmode: 'Opaque'
};
const styleObj = {
position: 'absolute',
top: '-999px',
left: '-999px',
};
Object.entries(attrObj).forEach(([key, value])=> iframeDom.setAttribute(key, value));
Object.entries(styleObj).forEach(([key, value])=> iframeDom.style[key] = value);
document.body.insertBefore(iframeDom, document.body.children[0]);
const iframeWin = iframeDom.contentWindow;
const iframeDocs = iframeWin.document;
iframeDocs.write(`<!doctype html>`);
iframeDocs.write(htmlTemp);
iframeWin.focus();
iframeWin.print();
document.body.removeChild(iframeDom);
}
printPartial(document.querySelector('#description'));
复制代码
最后一些注意的事情
<header>
里面的参考: