javascript 如何计算打印 HTML 的 CSS 分页符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4650482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 14:25:50  来源:igfitidea点击:

How can I count CSS page breaks for printed HTML?

javascripthtmlcssprinting

提问by Carvell Fenton

I am generating reports using HTML and I am using CSS to control the page breaking using page-break-after, etc. I have given the user the option to print multiple reports at once, which I create as sections of a single dynamically generated HTML document. Making it a single document allows it to be a single print job to avoid print spooling issues.

我正在使用 HTML 生成报告,我正在使用 CSS 来控制使用 page-break-after 等的分页。我为用户提供了一次打印多个报告的选项,我将其创建为单个动态生成的 HTML 的部分文档。使其成为单个文档可以使其成为单个打印作业,以避免打印假脱机问题。

My problem is this: I would like to number the pages of a section of the larger dynamic HTML in the format "page x of n". However, if I let the printer do it, it sees the document (rightly) as a single document and numbers the whole document.

我的问题是这样的:我想以“page x of n”格式对较大动态 HTML 的一部分的页面进行编号。但是,如果我让打印机执行此操作,它会将文档(正确地)视为单个文档并为整个文档编号。

Is there any way I could determine when the CSS page breaks are going to occur, so I could count them for a section before printing, and put my own numbering (HTML element for example) in for the sections in the long single document?

有什么方法可以确定何时将发生 CSS 分页符,以便我可以在打印前将它们计算为一个部分,并为长单个文档中的部分添加我自己的编号(例如 HTML 元素)?

It seems like there should be a way for me to do this, but over the past few days the solution eludes me, so I thought I would ping Stackoverflow.

似乎应该有一种方法可以让我做到这一点,但在过去的几天里,我没有找到解决方案,所以我想我会 ping Stackoverflow。

UPDATE: What I ended up doing:

更新:我最终做了什么:

I have accepted Christopher's answer because although I didn't use it exactly, it pointed me in the right direction.

我接受了克里斯托弗的回答,因为虽然我没有完全使用它,但它为我指明了正确的方向。

I ended up doing calculations on the content using jQuery, based on the paper size being printed to, margins, font size, etc. and then adding elements for page breaks that have CSS for page breaking. I track how many of the page break divs are added, and then update the html "page x of n" information in each page break div once all the content is processed. That allowed me to avoid having to know how many pages there would be at the beginning (thanks jQuery .each).

我最终使用 jQuery 对内容进行了计算,基于打印到的纸张大小、边距、字体大小等,然后为具有用于分页的 CSS 的分页符添加元素。我跟踪添加了多少分页符 div,然后在处理完所有内容后更新每个分页符 div 中的 html“page x of n”信息。这让我不必知道开头会有多少页(感谢 jQuery .each)。

Obviously there are some issues with this solution:

显然,这个解决方案存在一些问题:

  1. The "page x of n" elements don't appear as true footers, but rather at the bottom of the content on each page. In my situation that is an acceptable compromise.

  2. Splitting content elements that were in themselves larger than a page, especially considering most of the content is generated by php, got a little complicated. I made it work, but again, it requires assumptions that could break with printing variations.

  3. The calculations depend on assumptions about the printed paper size, margins, font size, etc. In my situation running on an intranet, that is again an acceptable compromise because I can control those options. Additional code can be added to handle some amount of variation in future (paper size for example).

  1. “第 x 页,共 n 个”元素不会作为真正的页脚出现,而是出现在每页内容的底部。在我的情况下,这是一个可以接受的妥协。

  2. 拆分本身比页面大的​​内容元素,特别是考虑到大部分内容是由 php 生成的,这有点复杂。我让它工作了,但同样,它需要可能因印刷变化而中断的假设。

  3. 计算取决于对打印纸张大小、边距、字体大小等的假设。在我在 Intranet 上运行的情况下,这又是一个可以接受的折衷方案,因为我可以控制这些选项。可以添加额外的代码来处理未来的一些变化(例如纸张尺寸)。

This solution, although not perfect and a little "brittle", solves my problem, allows me to print multiple reports at once avoiding printer spooling timeouts, keeps track of and restarts page numbering, and avoids generating PDFs as an intermediate step for printing.

该解决方案虽然不完美且有点“脆弱”,但解决了我的问题,允许我一次打印多个报告,避免打印机假脱机超时,跟踪并重新启动页码,并避免生成 PDF 作为打印的中间步骤。

I found this a oddly hard nut to crack, so I would still appreciate opinions and input on the solution.

我发现这是一个奇怪的难以破解的难题,所以我仍然会感谢对解决方案的意见和投入。

Thanks!

谢谢!

UPDATE 2: Final solution... avoid the headaches yourself:

更新 2:最终解决方案......自己避免头痛:

Although I went perhaps farther than I should have with this approach, with some small successes, in the end the solution really wasn't one because it just ended up being far too "brittle" to changes. Any change in report format, new content added to existing reports, paper size etc. broke the calculations and just ended up in a ridiculous amount of extra work!

尽管我用这种方法可能走得比我应该走的更远,取得了一些小小的成功,但最终解决方案真的不是一个,因为它最终太“脆弱”而无法改变。报告格式的任何更改、现有报告中添加的新内容、纸张大小等都会破坏计算,最终导致大量额外工作!

So, the end solution? "Resistance is futile!" Just do the reports as PDFs. You may commence the "we told you so" chorus if you wish, I can take it ;-)

那么,最终的解决方案?“抵抗是徒劳的!” 只需将报告制作为 PDF 即可。如果你愿意,你可以开始“我们告诉过你”的合唱,我可以接受;-)

I went with the TCPDFlibrary, which has been excellent, if a little tough going to get started. The examples are very helpful. Now I have complete customization over the report, and everything get generated as it should. Mulitple reports are easily created as a single PDF (preventing the print spooling issue) with page groups that allows for the numbering to work exactly as I need.

我选择了TCPDF库,它非常棒,但上手有点困难。这些例子非常有帮助。现在我对报告进行了完全自定义,并且所有内容都按预期生成。多份报告很容易创建为单个 PDF(防止打印假脱机问题),页面组允许编号完全按照我的需要工作。

So, if you are trying to do something like this, I would recommend you cut to the chase, skip the frustration with HTML/CSS type reports, and do PDFs.

因此,如果您正在尝试做这样的事情,我建议您切入正题,跳过 HTML/CSS 类型报告的挫败感,并制作 PDF。

采纳答案by Christopher

Ive been able to implement page breaks whilst creating PDFs for print, using wkhtmltopdf. though im not sure if my solution is compatible with non webkit browsers but im sure you can get a vendor prefix for all the broswers if needs be.

我已经能够在使用 wkhtmltopdf 创建用于打印的 PDF 时实现分页符。尽管我不确定我的解决方案是否与非 webkit 浏览器兼容,但我确定如果需要,您可以获得所有浏览器的供应商前缀。

Heres what i did, using page-break-inside: avoid;& page-break-after: always;

这是我所做的,使用page-break-inside: avoid;&page-break-after: always;

Then using jquery I worked out the heights of my sections and calculated (if the page size is going to be a4) how many times a break occured, and numbered the pages dynamically using jquery and pdf footers (before creating the pdf) so when the user downloaded the pdf it was numbered correctly.

然后使用 jquery 我计算出我的部分的高度并计算(如果页面大小将是 a4)中断发生的次数,并使用 jquery 和 pdf 页脚(在创建 pdf 之前)动态地对页面进行编号,所以当用户下载了正确编号的pdf。

What I reccomend is setting the page up (as the print stylesheet) so that page numbers are visible at these heights in the page, using absolute positionsing perhaps.

我推荐的是设置页面(作为打印样式表),以便页码在页面中的这些高度可见,也许使用绝对定位。

but I dont think this is failsafe.

但我不认为这是故障安全的。

Give them a PDF to print, then you have more control and dont have to worry about the web-print stylesheet, provided the PDF download link is prominently dispalyed.

给他们一个要打印的 PDF,然后你就有更多的控制权,不必担心网络打印样式表,只要 PDF 下载链接显眼地显示出来。

回答by Carvell Fenton

This will display page numbers, but not the total number of pages:

这将显示页码,但不显示总页数:

footer {
    position:fixed;
    bottom:0;
    left:0;
}

body {
    counter-reset: page_number;
}

#page-number:after {
    counter-increment: page_number;
    content: "Page " counter(page_number);
}

Having something like

有类似的东西

<p id='page-number'></p>

in the footer.

在页脚中。

Browser: Firefox 19.0.2

浏览器:火狐 19.0.2

回答by Sparafusile

I'm assuming you place a CSS page break at the end of each report and not manually at the end of each page. So your problem is to know when a page break will occur naturally within a long HTML document. The answer is - you can't. Even if you know how many lines of a table fit on a page (for example) you'll only know that for a given page size and print settings. If somebody decides to print your report on legal paper scaled 200% then your document will never know that. In my opinion, your options are 1) guess or 2) don't worry about it.

我假设您在每个报告的末尾放置了一个 CSS 分页符,而不是在每个页面的末尾手动放置。因此,您的问题是要知道何时在长 HTML 文档中自然会出现分页符。答案是——你不能。即使您知道一个页面上有多少行(例如),您也只会知道给定页面大小和打印设置的情况。如果有人决定在 200% 比例的法律纸张上打印您的报告,那么您的文档将永远不会知道这一点。在我看来,您的选择是 1) 猜测或 2) 不要担心。

回答by Tom Clarkson

You can't count page breaks, but you can count column breaks, which behave very similarly.

您不能计算分页符,但可以计算分栏符,它们的行为非常相似。

Wherever you have page break styles, pair them with a matching column break:

无论您在哪里有分页符样式,都可以将它们与匹配的分栏符配对:

-webkit-column-break-inside: avoid;
-webkit-break-inside: avoid;

Then set the report to use columns that match the size of a printed page:

然后将报告设置为使用与打印页面大小匹配的列:

.page.precalc {
    width: 16800mm;
    height: 257mm;
    -webkit-column-width: 168mm;
    .content {
        width: 168mm;
    }
}

Column breaks work very similarly to page breaks, so you can determine the page number of an element simply by measuring the horizontal position.

分栏符的工作方式与分页符非常相似,因此您可以通过测量水平位置来确定元素的页码。

var left = el.getBoundingClientRect().left;
pageNumber = Math.round(left/635) + 1

CSS columns still have somewhat spotty support, so may not print correctly. However, you can remove the .precalc style as soon as you are done with layout calculations, so that the view will return to the original vertical layout. Depending on use case, a screen/print media query could also work.

CSS 列仍然有一些参差不齐的支持,因此可能无法正确打印。但是,您可以在完成布局计算后立即删除 .precalc 样式,以便视图返回原始垂直布局。根据用例,屏幕/印刷媒体查询也可以工作。

The above works for me to generate a table of contents with phantomjs. Getting it to work in an arbitrary browser controlled by the user is somewhat more complex.

以上对我来说用 phantomjs 生成目录。让它在用户控制的任意浏览器中工作有点复杂。

回答by dmn

The following snippet will produce; a print page break before each h2on the page.

以下代码段将产生;在页面h2上的每个之前打印分页符。

extracted from here

这里提取

<style type="text/css">
  h2 {
    page-break-before: always;
  }
</style>