1.目测你的需求可能类似于有一个下拉框让用户选择纸张大小,然后用js监听这个change事件在回调中动态改变相应的@page。所以你这个问题其实归结为js动态调整css的问题。那这样的问题其实比较容易解决,下面是两种思路
2.css中在不同的class下定义不同的@page的pagetype页面类型,然后在js中给要打印的区域的父级盒添加不同的class。伪代码如下:
<style> @page pagea4{ //声明一个页面类型pagea4,类似于@keyframe用法 声明一个动画 size:A4 portrait;//定义大小以及纵横向,landscape横向,portrait纵向 } @page pagea3{ //同上 size:A3 landscape; } body.print-a3{ page:pagea3; //使用page样式来指定一个页面类型 } body.print-a4{ page:pagea4; } </style> <script> document.getElementById('select').addEventListener('change',function(){ if(this.value=='a4'){ document.body.className = 'print-a4' } if(this.value=='a3'){ document.body.className = 'print-a3' } }) </script>
3.另一种思路跟上面类似,在源码的getStyle中再加入一段js动态写入一段@page样式,伪代码如下:
getStyle: function() { var str = "", styles = document.querySelectorAll('style,link'); for (var i = 0; i < styles.length; i++) { str += styles[i].outerHTML; } if(document.getElementById('select').value == 'a4'){ str += '<style>@page{size:a4 portrait}</style>' } return str; }
P.S.参考文档
https://developer.mozilla.org/zh-CN/docs/Web/CSS/@page MDN文档 http://www.php.cn/css-tutorial-373189.html http://www.softwhy.com/article-5613-1.html
借楼下的问题再分享下如何调试打印样式的问题。
因为打印预览在chrome中是无法用devtool查看打印嵌入的<embed>插件对象样式的,所以打印样式没有符合预期时,一般调试都是去改打印前页面里的样式,再预览打印,就像不打断点调试js一样,相当耗时间。
1.弹出打印预览时会把js线程挂起来(==临时断点),而且是像“截图”一样把打印时的页面截取成pdf,意味着如果在调用打印方法前,异步执行了大量DOM操作,很可能在DOM还没渲染完成就被“截取了”,所以这种场景下推荐延时400~600ms再调用打印,保证DOM渲染完成
2.在主函数Print原型链上的writeIframe中是通过创建框架apped到body中,然后在同源下取得框架的contentWindow与contentDocument(=doc),再通过
doc.open()→doc.write(html)→doc.close()
打开文档流,写入DOM字符串,关闭文档流并渲染DOM来实现样式与html的“注入”。那么同样地,可以通过window.open()打开一个新窗口(标签页),同样取得window和document对象,再把要打印的html及其样式在新窗口中打开,此时就能用devtool调试不符合预期的样式了。代码示例如下:
var newWin = window.open() var newDoc = newWin.document newDoc.title = "打印窗口" newDoc.open() newDoc.write('123') newDoc.close()回复
再分享三个打印的小窍门:
1.怎么用css去掉页眉页脚但是保持页边距?如下:
@page{ size:auto;margin:0mm; }
这句css将页宽设为自适应、页边距设为0mm,浏览器发现没有页眉页脚空间,就不会加一堆网址、页码、时间、页面title的信息
html{font-size:100%;} body{padding:2.22rem 2.7rem;}
这句则将1rem设定为16px,然后利用body的padding来留出页边距。这个padding数值是根据多次测试得来的,比较粗略,对应的是A4标准-上下2.54mm,左右3.09mm
2.(可能有些情况不需要)有些打印机打出来发现顺时针歪了一个小角度,可以将body稍微旋转一下:
body { transform: rotate(-0.1 deg); - webkit - transform - origin: center center;transform - origin: center center; }
3.(可能有些情况不需要)有些页面点打印预览(非IE),发现最后多出来一页空白的,完全多余。
body{height: calc(100% - 1px) !important}
鼓捣了一下发现是因为body的高度为100%,撑满了页面,自动换行到下一页去了,多减掉1px(或者更多)貌似就可以了
1.针对第2点对第3点修正下,在某些页面下,把body transform变换也会导致多一个空白页。究其原因,就是body逆时针旋转了一个角度,把文档流当成一个父级盒,不难想象,body肯定会上下露出两个角来。而打印的范围是按照文档流来处理的,所以会莫名其妙多出来一个空白页。
2.如果需要实现第2点的效果,可以给打印内容嵌套一个父级盒再使用上述的样式,但是依然不保证不会超出文档流,transform变换需要根据实际情况谨慎使用。
3.除了上一点中提到的情况之外,普通情况调试页面下也可以通过添加
html * { border:1px #f00 solid !important; } // 红色边框线或其他醒目的样式
来查看到底是哪个元素超出了文档流,当然也不要忘记标准模式(content-box)和怪异模式(border-box)的影响
先说明非作者哈XD
简单注释下:
主函数:
初始化打印dom 排除非打印区域
原型链:
init:调用链方法getStyle和getHtml将样式与dom字符串组装起来 write将该组装片段写入中
extend:对象浅层扩展封装
getStyle:从当前页面获取style标签和link标签 附加no-print隐藏样式 以写入
getHtml:获取主函数中附着在this原型上的指定dom对象 并且将当前input、textarea、select的状态、内容二次赋值,以便在写入的时候能渲染出一样的结果
write:将组装好的html字符串写入的DOM,其中doc.open()为打开写入文档流,才能写入内容,doc.close()为关闭写入文档流,以结束的load状态,其他的应该不难理解。
点击打印空白问题(有时):是因为加载与打印是异步执行的,很容易导致在document.execCommand('print')的时候,还没加载出来,所以是一片空白。针对修改如下,将write方法与toPrint方法合并了。
write: function(content) { var w, doc, = document.createElement(''), f = document.body.appendChild(); .id = "print-"; .src = ''; .style = "position:absolute;width:0;height:0px;top:-10px;left:-10px;"; w = f.contentWindow || f.contentDocument; doc = f.contentDocument || f.contentWindow.document; doc.open(); doc.write(content); doc.close(); w.onload = function() { try { setTimeout(function() { w.focus(); try { if (!w.document.execCommand('print', false, null)) { w.print(); } } catch (e) { w.print(); } w.close(); }, 10); } catch (err) { console.log('err', err); } setTimeout(function() { document.body.removeChild(); }, 100); }; }回复
请问各位大神, 为什么部分样式失效, 特别是使用定位,预览布局都乱的, 有什么好的方法解决吗
插件中获取样式的代码:
getStyle: function() { var str = "", styles = document.querySelectorAll('style,link'); console.log(styles); for (var i = 0; i < styles.length; i++) { str += styles[i].outerHTML; } return str; }
我简单试了一下fixed和absolute定位,打印预览时排版是正常的。建议依次排查原因:
1. 因为使用了querySelectorAll,兼容性不是那么好,不知道你的浏览器是否支持。
2.你可以把获取到的styles打印一下,看看是否完整。
3.如果background-color丢失,在css中添加:
@media print { body{-webkit-print-color-adjust:exact;} }