写在前面
这几天朋友项目中还在使用window.print,结果问题它又来了。我写了个demo模拟遇到问题的场景,先看效果:
看过我前一篇关于print的文章的小伙伴都很熟悉这个界面吧,上次截的时候就有这个页眉页脚了,但上次他没有提这个地方。这次发现问题了,就来解决一下。
言归正传,那想去掉这个其实很简单,只要在浏览器设置中把页眉页脚勾掉就可以了:
但还是那句话,你可能给每一个用这个项目的客户说,你要在打印之前去浏览器设置里把页眉页脚勾掉吗?
显然是不可能的。所以像上次的背景水印一样,我们还是需要用代码来实现去掉页眉页脚的效果。
发现问题
我们可以用以下代码去掉页眉页脚:
@media print{
@page{
margin: 0;
}
}
但是,这个地方就有问题了。
一页的时候还看不太出来,两页以上的话你会发现,因为是用伪类@page的外边距margin来去除页眉页脚的,这让每一页的内容都占满了整个页面,也就是:
可能光是背景图看不太出来,我用循环在页面上填充了4500个“的”:
for(var i = 0;i < 4500;i++){
document.getElementsByClassName('container')[0].innerHTML += '的';
}
现在页面是这样的(有点眼花。。但这样填充页面是最方便的,为了下面测断开处的效果):
可以看到,在自动分页时,超出一页的部分会断开,但因为上面把margin设置为0了,每页的内容都是贴着边的。用过打印机的都知道,打印时它会留一个白边,如果你的页面内容贴着边,就会被遮挡,像这样:
我只拍了左边,上边右边下边如果有遮挡也是这样的。这显然不是我们要的效果。
于是我想到,那我给它的body加个margin值让它不贴边不就好了:
body{
margin: 20px;
}
但是预览的时候我发现第一页是可以的,第二页没有用。因为自动分页之后的第二页还是和第一页同一个body。也可以说,他们是同一个body,不同的page:
可是对于page的话,我之前用伪类@page已经设置了margin为0了,如果再改变margin值就没有任何意义了。于是我想到,既然margin不行,我就用padding好了。
但很可惜的是,对于伪类@page来说,它的文档上是这样写的:
翻译过来就是说:@page 规则用于在打印文档时修改某些CSS属性。你不能用@page规则来修改所有的CSS属性,而是只能修改margin,orphans,widow 和 page breaks of the document。对其他属性的修改是无效的。
这告诉我padding也不行。那在只能针对每个page下手,在page只能修改margin的情况下,我只能从margin上做文章,来实现我想要的效果。
解决方案
于是我就试着直接在给@page的margin值时,不给0,而是给一个定值。
@media print{
@page{
margin: 22px 10px 16px;
}
}
意外的发现竟然是可行的,不仅没有页眉页脚了,页面内容也不贴边了:
什么原理呢?我又多试了几个值,结果发现当大于比如30px的时候,页眉页脚还是会出来,说明并不是页眉页脚没了,而是打印的时候,浏览器自动加的页眉页脚也留出了打印机的那个空白边。于是我猜测,只要我留出的空白和浏览器自动加的页眉页脚时留出的空白一样多,那么不仅不会出现页面打印不全被遮挡的问题,也不会出现页眉页脚了。
这是一个比较笨的办法,但确实也是可行的。上文代码中的margin值是我打印了6次浪费了12张纸后得到的一个既不会遮挡,也不会出现页眉页脚的值。但并不是最精确的,还可以继续调整,但我就不继续测了。
为了防止由于我填充页面的时候全用的是同一个字,页面有遮挡但我没看出来的情况出现,我又在循环里加了指定的两个字:
for(var i = 0;i < 4500;i++){
if(i == 2396){
document.getElementsByClassName('container')[0].innerHTML += '一'
} else if(i == 2397){
document.getElementsByClassName('container')[0].innerHTML += '二'
} else {
document.getElementsByClassName('container')[0].innerHTML += '的'
}
}
现在页面变成这样:
打出来也是这样的,没有被遮挡的地方。(注意光看预览效果是看不到被遮挡的,一定要去打出来看):
小结
window.print使用起来还是有不少问题的,我碰到的多是因为页面超出一页自动分页之后,由于无法对每个页面处理,每次处理的时候要么就是整个body,所以很多问题不好解决。
有的小伙伴可能会问我为什么不用page breaks手动分页,但是我实际用在项目中的时候,一页有多少内容,一共有多少页,都是不固定的,而且有的内容还嵌套在表格里,还有表格被撑开,表格从中间断开等问题,这就更不好用page breaks来处理了。当然,想这样处理也是可以的,只要先把表格渲染在页面上,但不显示,计算好一共要多少页面,每个页面什么地方断开,每个表格多高,什么地方断开,然后再用新的盒子把内容放进去显示,再添加page breaks来分页,这样应该也行,但是挺麻烦的。
只是这个项目因为不是我的,我只是帮忙解决遇到的问题,不好对整个项目修改太多。我也和人家讲了这个思路,人家是否采纳就是后话了。
浏览器兼容性的问题,有不少大佬都写了博客,我这边就不再啰嗦了。上述代码chrome可用,360可用,没测其他。其他浏览器特别是IE怎么处理,大家直接看大佬的文章就可以了。