iframe页面的打印父窗口导致奇数缩放

时间:2011-07-11 06:28:12

标签: css iframe printing zoom

我的任务是将几个HTML文档合并到一个页面中进行打印。我的第一次尝试失败了 - 我试图将每个页面内容隔离在他们自己的<div>标签和修改后的样式表规则中以匹配。我使用iframe隔离每个文档的第二次尝试看起来明显更好,但是从iframe堆栈的父框架打印时,页面会被放大,而不是在自己的窗口中单独打印文档。

以下是我正在使用的文档示例:http://dl.dropbox.com/u/291229/print-test/index.html

您可以在Firefox中进行打印预览,看看我的意思。如果您在其自己的选项卡/窗口中打开第一帧并打印预览,则轮廓框很适合页面。在iframe堆栈的父窗口中执行相同操作会显示在页面边界外流动的单元格。

免责声明:我没有对这些网页进行编码。是的,我知道他们很可怕。遗憾的是,该项目没有时间或预算来重新编写页面,以实现打印一组文档的单页目标。我可能会暂时要求用户单独打印每个页面以进行适当的缩放,但我仍然想了解可能导致此问题的原因。

2 个答案:

答案 0 :(得分:9)

问题是浏览器使用容器iframe的宽度来确定如何缩放该帧的内容以进行打印。因此,框架需要明确确定其宽度。

不幸的是,动态计算出打印宽度非常棘手并且涉及一些hackery。您可能最好只设置固定宽度的组件页面并将iframe宽度硬编码为。

但是,如果您确实需要动态调整它们的大小,则可以在加载文档(在Chrome中测试)后运行以下代码:

var iframes = document.getElementsByTagName("iframe");
for(var i = 0; i < iframes.length; ++i) {
    var curFrame = iframes[i];
    var curBody = curFrame.contentDocument.body;
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden; white-space: nowrap;">'
                      +  curBody.innerHTML + '</div>';
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content");
    var curWidth = printContent.offsetWidth + printContent.offsetLeft;
    iframes[i].style.width=(curWidth + "px");
}

运行此功能后,您可以正常打印或致电window.print()或做任何您想做的事。


注意:此方法在ie6或ie7上不能正常工作,因为它们不支持inline-block。 (还有一些其他较旧的浏览器也没有)。当然,您可以尝试

display:-moz-inline-stack; display:inline-block; zoom:1; *display:inline; overflow:hidden; white-space: nowrap;

相反,它可能会处理大多数这些情况,但我对旧浏览器不作任何承诺。

祝你好运,很遗憾听到您在这些页面上遇到密码。




编辑:上述解决方案在Firefox中有点不稳定。

Firefox解决方案(在Firefox 5中测试和使用):

var iframes = document.getElementsByTagName("iframe");
for(var i = 0; i < iframes.length; ++i) {
    var curFrame = iframes[i];
    var curBody = curFrame.contentDocument.body;
    var oldHTML = curBody.innerHTML;
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden;">' +  oldHTML + '</div>';
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content");
    var curWidth = printContent.offsetWidth + printContent.offsetLeft + 25;
    var curHeight = printContent.offsetHeight + printContent.offsetTop + 25;
    curBody.innerHTML = oldHTML;
    iframes[i].style.width=(curWidth + "px");
    iframes[i].style.height=(curHeight + "px");
}

要完整解释为什么这种一般方法有效,请参阅上面的答案。

与上述解决方案有何不同,为什么?

首先,Firefox的细节:
有一些关键的区别。第一个注意到Firefox处理display: inline-blockwhite-space: nowrap的方式不同于Chromium / WebKit的固定宽度元素(这就是为什么一个文档看起来真的很难用前面的代码)。接下来注意到Firefox喜欢在其iframe中提供一点保证金。我不太熟悉执行此操作的Firefox代码(花费我的时间来攻击Chromium),但我通常的解决方案(除了避免使用框架)只是在边距上额外增加25px。像这样的一点点似乎是解决这类问题的流行黑客。

现在,代码中实际上更好的部分:
首先,它现在存储旧体,将身体提升到div上进行测量,然后恢复旧体。这应避免CSS不灵活的问题,并应保证更可预测的行为。其次,这对于高度和宽度做了同样的事情(我之前的假设是硬编码的宽度才有效,但无论如何这都是一个更灵活的解决方案。)

为什么这还不错?

删除white-space: nowrap将在Chromium / WebKit上打印文本。它仍然打印很好,但它不完全正确,因为一些额外的文本将包装。为了使其成为真正可行的解决方案,您仍然需要执行浏览器检测代码。

同样,我建议使用此代码快速找出适当的宽度和高度,然后测试并硬编码每个浏览器的正确尺寸。这是一个丑陋的解决方案,但它最终是这种情况下唯一真正强大的解决方案。

答案 1 :(得分:1)

我相信你可以(再次)通过向中间的一个iFrame添加静态宽度来“欺骗”浏览器...这会强制打印版本调整大小,将所有信息重新带回页面......我只修改了这个iFrame并重新调整了尺寸(注意宽度:150%):

<iframe src="order/form.html" style="height: 1707px;width:150%">