Html 在打印页面上使用 Google Chrome 重复表格标题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7211229/
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
Having Google Chrome repeat table headers on printed pages
提问by Stephen M
I'd like to have my table's headers repeated for every printed page, but it seems Google Chrome doesn't support the <thead>
tag well...is there a way around this? I'm using Google Chrome v13.0.782.215.
我想为每个打印页面重复我的表格标题,但似乎谷歌浏览器不能<thead>
很好地支持该标签......有没有办法解决这个问题?我正在使用谷歌浏览器 v13.0.782.215。
The table code is very straightforward...nothing fancy:
表格代码非常简单……没什么特别的:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css" media="all">
@page {
size: landscape;
margin-top: 0;
margin-bottom: 1cm;
margin-left: 0;
margin-right: 0;
}
table {
border: .02em solid #666; border-collapse:collapse;
width:100%;
}
td, th {
border: .02em solid #666; font-size:12px; line-height: 12px;
vertical-align:middle; padding:5px; font-family:"Arial";
}
th { text-align:left; font-size:12px; font-weight:bold; }
h2 { margin-bottom: 0; }
</style>
</head>
<body>
<h2>Page Title</h2>
<table>
<thead>
<tr class="row1">
<th><strong>Heading 1</strong></th>
<th><strong>Heading 2</strong></th>
<th><strong>Heading 3</strong></th>
<th><strong>Heading 4</strong></th>
<th><strong>Heading 5</strong></th>
</tr>
</thead>
<tbody>
<tr class="row2">
<td width="30">...</td>
<td width="30">...</td>
<td width="90">....</td>
<td width="190">...</td>
<td width="420">...</td>
</tr>
<tr class="row1">
<td width="30">...</td>
<td width="30">...</td>
<td width="90">....</td>
<td width="190">...</td>
<td width="420">...</td>
</tr>
....
</tbody>
</table>
</body>
</html>
Any insight into this is welcome.
欢迎对此有任何见解。
回答by DoctorDestructo
UPDATE 2017-03-22: Repeating table headers have finally been implemented in Chrome!(Actually, I think they were implemented some time ago.) That means you probably don't need this solution anymore; just put your column headers in a <thead>
tag and you should be all set. Use the solution below only if:
更新 2017-03-22:重复表头终于在 Chrome 中实现了!(实际上,我认为它们是在一段时间前实施的。)这意味着您可能不再需要此解决方案;只需将您的列标题放在一个<thead>
标签中,您就应该全部设置好了。仅在以下情况下使用以下解决方案:
- you encounter show-stopping bugs in Chrome's implementation,
- you need the "bonus features", or
- you need to support some oddball browser that still doesn't support repeating headers.
- 你在 Chrome 的实现中遇到了停止显示的错误,
- 您需要“奖励功能”,或
- 您需要支持一些仍然不支持重复标题的奇怪浏览器。
SOLUTION (obsolete)
解决方案(已过时)
The code below demonstrates the best method I've found for multi-page table printing. It has the following features:
下面的代码演示了我发现的用于多页表格打印的最佳方法。它具有以下特点:
- Column headers repeat on each page
- No need to worry about paper size or how many rows will fit-- the browser handles everything automatically
- Page breaks occur only between rows
- Cell borders are always fully closed
- If a page break occurs near the top of the table, it won't leave behind an orphaned caption or column headers with no data attached (a problem which isn't limited to just Chrome)
- Works in Chrome! (and other Webkit-based browsers like Safari and Opera)
- 列标题在每一页上重复
- 无需担心纸张大小或适合多少行——浏览器会自动处理所有内容
- 分页符仅发生在行之间
- 单元格边框始终完全关闭
- 如果分页符发生在表格顶部附近,它不会留下孤立的标题或没有附加数据的列标题(这个问题不仅限于 Chrome)
- 在 Chrome 中工作!(以及其他基于 Webkit 的浏览器,如 Safari 和 Opera)
... and the following known limitations:
...以及以下已知限制:
- Only supports 1
<thead>
(which is apparently the most you're allowed to haveanyway) - Doesn't support
<tfoot>
(though Chrome-compatible running footers are technically possible) - Only supports top-aligned
<caption>
- Table can't have top or bottom
margin
; to add white space above or below the table, insert an empty div and set a bottom margin on it - Any CSS size values that affect height (including
border-width
andline-height
) must be inpx
Column widths can't be set by applying width values to individual table cells; you should either let cell content automatically determine column width, or use
<col>s
to set specific widths if neededTable can't (easily) be changed dynamically after the JS has run
- 只支持 1
<thead>
(这显然是你被允许拥有的最多) - 不支持
<tfoot>
(尽管 Chrome 兼容的运行页脚在技术上是可行的) - 仅支持顶部对齐
<caption>
- 表不能有顶部或底部
margin
;要在表格上方或下方添加空白,请插入一个空的 div 并在其上设置底部边距 - 任何影响高度(包括
border-width
和line-height
)的CSS 大小值都必须在px
不能通过将宽度值应用于单个表格单元格来设置列宽;您应该让单元格内容自动确定列宽,或者
<col>s
根据需要使用设置特定宽度JS 运行后,表不能(容易)动态更改
THE CODE
编码
<!DOCTYPE html>
<html>
<body>
<table class="print t1"> <!-- Delete "t1" class to remove row numbers. -->
<caption>Print-Friendly Table</caption>
<thead>
<tr>
<th></th>
<th>Column Header</th>
<th>Column Header</th>
<th>Multi-Line<br/>Column<br/>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>data</td>
<td>Multiple<br/>lines of<br/>data</td>
<td>data</td>
</tr>
</tbody>
</table>
</body>
</html>
<style>
/* THE FOLLOWING CSS IS REQUIRED AND SHOULD NOT BE MODIFIED. */
div.fauxRow {
display: inline-block;
vertical-align: top;
width: 100%;
page-break-inside: avoid;
}
table.fauxRow {border-spacing: 0;}
table.fauxRow > tbody > tr > td {
padding: 0;
overflow: hidden;
}
table.fauxRow > tbody > tr > td > table.print {
display: inline-table;
vertical-align: top;
}
table.fauxRow > tbody > tr > td > table.print > caption {caption-side: top;}
.noBreak {
float: right;
width: 100%;
visibility: hidden;
}
.noBreak:before, .noBreak:after {
display: block;
content: "";
}
.noBreak:after {margin-top: -594mm;}
.noBreak > div {
display: inline-block;
vertical-align: top;
width:100%;
page-break-inside: avoid;
}
table.print > tbody > tr {page-break-inside: avoid;}
table.print > tbody > .metricsRow > td {border-top: none !important;}
/* THE FOLLOWING CSS IS REQUIRED, but the values may be adjusted. */
/* NOTE: All size values that can affect an element's height should use the px unit! */
table.fauxRow, table.print {
font-size: 16px;
line-height: 20px;
}
/* THE FOLLOWING CSS IS OPTIONAL. */
body {counter-reset: t1;} /* Delete to remove row numbers. */
.noBreak .t1 > tbody > tr > :first-child:before {counter-increment: none;} /* Delete to remove row numbers. */
.t1 > tbody > tr > :first-child:before { /* Delete to remove row numbers. */
display: block;
text-align: right;
counter-increment: t1 1;
content: counter(t1);
}
table.fauxRow, table.print {
font-family: Tahoma, Verdana, Georgia; /* Try to use fonts that don't get bigger when printed. */
margin: 0 auto 0 auto; /* Delete if you don't want table to be centered. */
}
table.print {border-spacing: 0;}
table.print > * > tr > * {
border-right: 2px solid black;
border-bottom: 2px solid black;
padding: 0 5px 0 5px;
}
table.print > * > :first-child > * {border-top: 2px solid black;}
table.print > thead ~ * > :first-child > *, table.print > tbody ~ * > :first-child > * {border-top: none;}
table.print > * > tr > :first-child {border-left: 2px solid black;}
table.print > thead {vertical-align: bottom;}
table.print > thead > .borderRow > th {border-bottom: none;}
table.print > tbody {vertical-align: top;}
table.print > caption {font-weight: bold;}
</style>
<script>
(function() { // THIS FUNCTION IS NOT REQUIRED. It just adds table rows for testing purposes.
var rowCount = 100
, tbod = document.querySelector("table.print > tbody")
, row = tbod.rows[0];
for(; --rowCount; tbod.appendChild(row.cloneNode(true)));
})();
(function() { // THIS FUNCTION IS REQUIRED.
if(/Firefox|MSIE |Trident/i.test(navigator.userAgent))
var formatForPrint = function(table) {
var noBreak = document.createElement("div")
, noBreakTable = noBreak.appendChild(document.createElement("div")).appendChild(table.cloneNode())
, tableParent = table.parentNode
, tableParts = table.children
, partCount = tableParts.length
, partNum = 0
, cell = table.querySelector("tbody > tr > td");
noBreak.className = "noBreak";
for(; partNum < partCount; partNum++) {
if(!/tbody/i.test(tableParts[partNum].tagName))
noBreakTable.appendChild(tableParts[partNum].cloneNode(true));
}
if(cell) {
noBreakTable.appendChild(cell.parentNode.parentNode.cloneNode()).appendChild(cell.parentNode.cloneNode(true));
if(!table.tHead) {
var borderRow = document.createElement("tr");
borderRow.appendChild(document.createElement("th")).colSpan="1000";
borderRow.className = "borderRow";
table.insertBefore(document.createElement("thead"), table.tBodies[0]).appendChild(borderRow);
}
}
tableParent.insertBefore(document.createElement("div"), table).style.paddingTop = ".009px";
tableParent.insertBefore(noBreak, table);
};
else
var formatForPrint = function(table) {
var tableParent = table.parentNode
, cell = table.querySelector("tbody > tr > td");
if(cell) {
var topFauxRow = document.createElement("table")
, fauxRowTable = topFauxRow.insertRow(0).insertCell(0).appendChild(table.cloneNode())
, colgroup = fauxRowTable.appendChild(document.createElement("colgroup"))
, headerHider = document.createElement("div")
, metricsRow = document.createElement("tr")
, cells = cell.parentNode.cells
, cellNum = cells.length
, colCount = 0
, tbods = table.tBodies
, tbodCount = tbods.length
, tbodNum = 0
, tbod = tbods[0];
for(; cellNum--; colCount += cells[cellNum].colSpan);
for(cellNum = colCount; cellNum--; metricsRow.appendChild(document.createElement("td")).style.padding = 0);
cells = metricsRow.cells;
tbod.insertBefore(metricsRow, tbod.firstChild);
for(; ++cellNum < colCount; colgroup.appendChild(document.createElement("col")).style.width = cells[cellNum].offsetWidth + "px");
var borderWidth = metricsRow.offsetHeight;
metricsRow.className = "metricsRow";
borderWidth -= metricsRow.offsetHeight;
tbod.removeChild(metricsRow);
tableParent.insertBefore(topFauxRow, table).className = "fauxRow";
if(table.tHead)
fauxRowTable.appendChild(table.tHead);
var fauxRow = topFauxRow.cloneNode(true)
, fauxRowCell = fauxRow.rows[0].cells[0];
fauxRowCell.insertBefore(headerHider, fauxRowCell.firstChild).style.marginBottom = -fauxRowTable.offsetHeight - borderWidth + "px";
if(table.caption)
fauxRowTable.insertBefore(table.caption, fauxRowTable.firstChild);
if(tbod.rows[0])
fauxRowTable.appendChild(tbod.cloneNode()).appendChild(tbod.rows[0]);
for(; tbodNum < tbodCount; tbodNum++) {
tbod = tbods[tbodNum];
rows = tbod.rows;
for(; rows[0]; tableParent.insertBefore(fauxRow.cloneNode(true), table).rows[0].cells[0].children[1].appendChild(tbod.cloneNode()).appendChild(rows[0]));
}
tableParent.removeChild(table);
}
else
tableParent.insertBefore(document.createElement("div"), table).appendChild(table).parentNode.className="fauxRow";
};
var tables = document.body.querySelectorAll("table.print")
, tableNum = tables.length;
for(; tableNum--; formatForPrint(tables[tableNum]));
})();
</script>
HOW IT WORKS(If you don't care, read no further; everything you need is above.)
它是如何工作的(如果您不在乎,请不要继续阅读;您需要的一切都在上面。)
Per @Kingsolmn's request, below is an explanation of how this solution works. It doesn't cover the JavaScript, which isn't strictly required (though it does make this technique much easier to use). Instead, it focuses on the generated HTML structures and associated CSS, which is where the real magic happens.
根据@Kingsolmn 的要求,下面解释了此解决方案的工作原理。它不包括 JavaScript,这不是严格要求的(尽管它确实使这项技术更易于使用)。相反,它专注于生成的 HTML 结构和相关联的 CSS,这才是真正神奇的地方。
Here's the table we'll be working with:
这是我们将使用的表格:
<table>
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row1</td><td>row1</td></tr>
<tr><td>row2</td><td>row2</td></tr>
<tr><td>row3</td><td>row3</td></tr>
</table>
(To save space, I gave it only 3 data rows; obviously, a multipage table would usually have more)
(为了节省空间,我只给了它 3 个数据行;显然,多页表通常会有更多)
The first thing we need to do is split the table into a series of smaller tables, each with its own copy of the column headers. I call these smaller tables fauxRows.
我们需要做的第一件事是将表拆分为一系列较小的表,每个表都有自己的列标题副本。我称这些较小的表为fauxRows。
<table> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row1</td><td>row1</td></tr>
</table>
<table> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row2</td><td>row2</td></tr>
</table>
<table> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row3</td><td>row3</td></tr>
</table>
The fauxRows are essentially clones of the original table, but with only one data row apiece. (If your table has a caption, though, only the top fauxRow should include it.)
fauxRows 本质上是原始表的克隆,但每个只有一个数据行。(不过,如果您的表格有标题,则只有顶部 fauxRow 应包含它。)
Next we need to make the fauxRows unbreakable. What does that mean? (Pay attention-- this is probably the most important concept in page break handling.) "Unbreakable" is the term I use to describe a block of content that can't be split between two pages*. When a page break occurs within the space occupied by such a block, the whole block moves to the next page. (Note that I'm using the word "block" informally here; I'm notreferring specifically to block level elements.) This behavior has an interesting side-effect that we'll make use of later on: it can expose content that was initially hidden due to layering or overflow.
接下来我们需要使 fauxRows牢不可破。这意味着什么?(注意——这可能是分页处理中最重要的概念。)“牢不可破”是我用来描述不能在两个页面之间拆分的内容块的术语*。当在这样一个块所占用的空间内发生分页时,整个块将移动到下一页。(请注意,我在这里非正式地使用了“块”这个词;我不是专门指块级元素。)这种行为有一个有趣的副作用,我们稍后会使用它:它可以公开内容最初由于分层或溢出而被隐藏。
We can make the fauxRows unbreakable by applying either of the following CSS declarations:
我们可以通过应用以下任一 CSS 声明使 fauxRows 牢不可破:
page-break-inside: avoid;
display: inline-table;
page-break-inside: avoid;
display: inline-table;
I usually use both, because the first is made for this purpose and the second works in older/noncompliant browsers. In this case, though, for simplicity's sake, I'll stick to the page-break property. Note that you will not see any change in the table's appearance after adding this property.
我通常同时使用两者,因为第一个是为此目的而制作的,第二个适用于较旧/不兼容的浏览器。但是,在这种情况下,为了简单起见,我将坚持使用分页属性。请注意,添加此属性后,您不会看到表格外观发生任何变化。
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row1</td><td>row1</td></tr>
</table>
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row2</td><td>row2</td></tr>
</table>
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row3</td><td>row3</td></tr>
</table>
Now that the fauxRows are unbreakable, if a page break occurs within a data row, it will shift to the next page along with its attached header row. So the next page will always have column headers at the top, which is our goal. But the table looks very strange now with all the extra header rows. To make it look like a normal table again, we need to hide the extra headers in such a way that they'll appear only when needed.
现在 fauxRows 是牢不可破的,如果在数据行中发生分页符,它将与附加的标题行一起移到下一页。所以下一页总是在顶部有列标题,这是我们的目标。但是现在表格看起来很奇怪,所有额外的标题行。为了让它再次看起来像一个普通的表格,我们需要隐藏额外的标题,以便它们只在需要时出现。
What we're going to do is put each fauxRow in a container element with overflow: hidden;
and then shift it upward so that the headers get clipped by the top of the container. This will also move the data rows back together so that they appear contiguous.
我们要做的是将每个 fauxRow 放在一个容器元素中overflow: hidden;
,然后将其向上移动,以便标题被容器的顶部剪掉。这也会将数据行移回一起,使它们看起来是连续的。
Your first instinct might be to use divs for the containers, but we're going to use the cells of a parent table instead. I'll explain why later, but for now, let's just add the code. (Once again, this will not affect the table's appearance.)
您的第一直觉可能是将 div 用于容器,但我们将改用父表的单元格。我稍后会解释原因,但现在,让我们只添加代码。(同样,这不会影响桌子的外观。)
table {
border-spacing: 0;
line-height: 20px;
}
th, td {
padding-top: 0;
padding-bottom: 0;
}
<table> <!-- parent table -->
<tr>
<td style="overflow: hidden;">
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row1</td><td>row1</td></tr>
</table>
</td>
</tr>
<tr>
<td style="overflow: hidden;">
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row2</td><td>row2</td></tr>
</table>
</td>
</tr>
<tr>
<td style="overflow: hidden;">
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row3</td><td>row3</td></tr>
</table>
</td>
</tr>
</table>
Notice the CSS above the table markup. I added it for two reasons: first, it prevents the parent table from adding white space between the fauxRows; second, it makes the header height predictable, which is necessary since we're not using JavaScript to calculate it dynamically.
注意表格标记上方的 CSS。我添加它有两个原因:第一,它阻止父表在 fauxRows 之间添加空格;其次,它使标题高度可预测,这是必要的,因为我们没有使用 JavaScript 来动态计算它。
Now we just need to shift the fauxRows upward, which we'll do with negative margins. But it's not as simple as you might think. If we add a negative margin directly to a fauxRow, it will remain in effect when the fauxRow gets bumped to the next page, causing the headers to get clipped by the top of the page. We need a way to leave the negative margin behind.
现在我们只需要将 fauxRows 向上移动,我们将使用负边距。但这并不像你想象的那么简单。如果我们直接给 fauxRow 添加一个负边距,当 fauxRow 撞到下一页时它会保持有效,导致页眉被页面顶部剪掉。我们需要一种方法来留下负边距。
To accomplish this, we'll insert an empty div above each fauxRow after the first and add the negative margin to it. (The first fauxRow is skipped because its headers should always be visible.) Since the margin is on a separate element, it won't follow the fauxRow to the next page, and the headers won't be clipped. I call these empty divs headerHiders.
为此,我们将在第一个 fauxRow 上方的每个 fauxRow 上方插入一个空的 div,并为其添加负边距。(第一个 fauxRow 被跳过,因为它的标题应该总是可见的。)由于边距位于一个单独的元素上,它不会跟随 fauxRow 到下一页,并且标题不会被剪裁。我将这些空的 div称为 headerHiders。
table {
border-spacing: 0;
line-height: 20px;
}
th, td {
padding-top: 0;
padding-bottom: 0;
}
<table> <!-- parent table -->
<tr>
<td style="overflow: hidden;">
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row1</td><td>row1</td></tr>
</table>
</td>
</tr>
<tr>
<td style="overflow: hidden;">
<div style="margin-bottom: -20px;"></div> <!-- headerHider -->
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row2</td><td>row2</td></tr>
</table>
</td>
</tr>
<tr>
<td style="overflow: hidden;">
<div style="margin-bottom: -20px;"></div> <!-- headerHider -->
<table style="page-break-inside: avoid;"> <!-- fauxRow -->
<tr><th>ColumnA</th><th>ColumnB</th></tr>
<tr><td>row3</td><td>row3</td></tr>
</table>
</td>
</tr>
</table>
That's it, we're done! On screen, the table should now look normal, with only one set of column headers at the top. In print, it should now have running headers.
就是这样,我们完成了!在屏幕上,表格现在应该看起来正常,顶部只有一组列标题。在打印中,它现在应该有正在运行的标题。
If you were wondering why we used a parent table instead of a bunch of container divs, it's because Chrome/webkit has a bug that causes a div-enclosed unbreakable block to carry its container to the next page with it. Since the headerHider is also in the container, it won't get left behind like it's supposed to, which leads to clipped headers. This bug only happens if the unbreakable block is the topmost element in the div with a non-zero height.
如果你想知道为什么我们使用父表而不是一堆容器 div,那是因为 Chrome/webkit 有一个错误,导致一个 div 封闭的牢不可破的块将其容器携带到下一页。由于 headerHider 也在容器中,因此它不会像预期的那样被抛在后面,这会导致标题被剪掉。仅当牢不可破的块是 div 中高度非零的最顶层元素时,才会发生此错误。
I did discover a workaround while writing this tutorial: you just have to explicitly set height: 0;
on the headerHider and give it an empty child div with a non-zero height. Then you can use a div container. I still prefer to use a parent table, though, because it has been more thoroughly tested, and it salvages the semantics to some extent by tying the fauxRows back together into a single table.
在编写本教程时,我确实发现了一个解决方法:您只需height: 0;
在 headerHider 上显式设置并为其提供一个非零高度的空子 div。然后你可以使用一个 div 容器。不过,我仍然更喜欢使用父表,因为它已经过更彻底的测试,并且通过将 fauxRows 重新绑定到单个表中,它在某种程度上挽救了语义。
EDIT:I just realized that the JavaScript-generated markup is slightly different in that it puts each fauxRow in a separate container table, and assigns the "fauxRow" className to it (the container). This would be required for footer support, which I intended to add someday but never did. If I were to update the JS, I might consider switching to div containers since my semantic justification for using a table doesn't apply.
编辑:我刚刚意识到 JavaScript 生成的标记略有不同,因为它将每个 fauxRow 放在一个单独的容器表中,并将“fauxRow”类名分配给它(容器)。这将是页脚支持所必需的,我打算有一天添加但从未添加。如果我要更新 JS,我可能会考虑切换到 div 容器,因为我使用表的语义理由不适用。
* There is one situation in which an unbreakable block canbe split between two pages: when it exceeds the height of the printable area. You should try to avoid this scenario; you're essentially asking the browser to do the impossible, and it can have some very strange effects on the output.
* 有一种情况可以将牢不可破的块拆分为两页:当它超过可打印区域的高度时。你应该尽量避免这种情况;你本质上是在要求浏览器做不可能的事情,它会对输出产生一些非常奇怪的影响。
回答by thefredzx
now it's possible to print in chrome using jQuery.... please try this code (i'm sorry forget who's the creator of this code before i modified - and my english language is not good :D hehehe)
现在可以使用 jQuery 在 chrome 中打印......请试试这个代码(对不起,在我修改之前忘记了谁是这个代码的创建者 - 我的英语不好:D hehehe)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>DOCUMENT TITLE</title>
<link rel="stylesheet" type="text/css" href="assets/css/bootstrap.css"/>
<style type="text/css">
@media print{
table { page-break-after:auto;}
tr { page-break-inside:avoid;}
td { page-break-inside:auto;}
thead { display:table-header-group }
.row-fluid [class*="span"] {
min-height: 20px;
}
}
@page {
margin-top: 1cm;
margin-right: 1cm;
margin-bottom:2cm;
margin-left: 2cm;';
size:portrait;
/*
size:landscape;
-webkit-transform: rotate(-90deg); -moz-transform:rotate(-90deg);
filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
*/
};
</style>
</head>
<body>
<div id="print-header-wrapper">
<div class="row-fluid">HEADER TITLE 1</div>
<div class="row-fluid">HEADER TITLE 2</div>
</div>
<div class="row-fluid" id="print-body-wrapper">
<table class="table" id="table_data">
<thead>
<tr><th>TH 1</th><th>TH 2</th></tr>
</thead>
<tbody>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
<tr><td>TD 1</td><td>TD 2</td></tr>
</tbody>
</table>
<div id="lastDataTable"></div>
</div>
<script type="text/javascript">
jQuery(document).ready(function()
{
var printHeader = $('#print-header-wrapper').html();
var div_pageBreaker = '<div style="page-break-before:always;"></div>';
var per_page = 25;
$('#table_data').each(function(index, element)
{
//how many pages of rows have we got?
var pages = Math.ceil($('tbody tr').length / per_page);
//if we only have one page no more
if (pages == 1) {
return;
}
//get the table we're splutting
var table_to_split = $(element);
var current_page = 1;
//loop through each of our pages
for (current_page = 1; current_page <= pages; current_page++)
{
//make a new copy of the table
var cloned_table = table_to_split.clone();
//remove rows on later pages
$('tbody tr', table_to_split).each(function(loop, row_element) {
//if we've reached our max
if (loop >= per_page) {
//get rid of the row
$(row_element).remove();
}
});
//loop through the other copy
$('tbody tr', cloned_table).each(function(loop, row_element) {
//if we are before our current page
if (loop < per_page) {
//remove that one
$(row_element).remove();
}
});
//insert the other table afdter the copy
if (current_page < pages) {
$(div_pageBreaker).appendTo('#lastDataTable');
$(printHeader).appendTo('#lastDataTable');
$(cloned_table).appendTo('#lastDataTable');
}
//make a break
table_to_split = cloned_table;
}
});
});
</script>
</body>
</html>
回答by DavidTaubmann
This is an enhancement still not available in Webkit, Blink, and Vivliostyle, rather than in other more "print oriented formatters" (Firefox, IE).
这是一个在 Webkit、Blink 和 Vivliostyle 中仍然不可用的增强功能,而不是在其他更“面向打印的格式化程序”(Firefox、IE)中。
You can check the issue for Google Chrome since version 4 here (6 years and 45 versions ago!), where we can appreciate it's got an owner lately (February 2016), who even seems to be working on it.
您可以在此处查看 Google Chrome 自第 4 版以来的问题(6 年和 45 个版本之前!),我们可以感谢它最近(2016 年 2 月)有一个所有者,他甚至似乎正在研究它。
Some talk has been also held in the W3where we can appreciate the concern upon it's usefulness:
Since repeating table headers and footers on a fragmentation break is generally a useful thing, I suggest we make a normative requirement and say that UAs must repeat header/footer rows when a table spans a break.
由于在碎片中断时重复表头和页脚通常是有用的,我建议我们制定一个规范要求并说当表格跨越中断时 UA 必须重复页眉/页脚行。
Meanwhile, the JS and Jquery codes from @DoctorDestructo and @thefredzx have been really useful for my users not using Firefox nor IE (most of them).
同时,来自@DoctorDestructo 和@thefredzx 的 JS 和 Jquery 代码对我不使用 Firefox 或 IE(大多数)的用户非常有用。
The first one to be aware of a new version that includes this feature, should notice it in here, many of us would appreciate it.
第一个知道包含此功能的新版本的人应该在这里注意到它,我们中的许多人都会很感激。
回答by ak85
From my testing in chrome setting display: table-row-group;
to the thead stops the issue happening.
从我在 chrome 设置display: table-row-group;
中的测试到 thead 停止了问题的发生。
eg if you try to print the below without the style you will see number on top of each page but if you add the style it only appears oncontextmenu.
例如,如果您尝试在没有样式的情况下打印以下内容,您将在每页顶部看到数字,但如果您添加样式,它只会出现在上下文菜单上。
<style>
thead {
display: table-row-group;
}
</style>
<table>
<thead>
<tr>
<th>number</th>
</tr>
</thead>
<tbody id="myTbody">
</tbody>
</table>
<script>
for (i = 1; i <= 100; i++) {
document.getElementById("myTbody").innerHTML += "<tr><td>" + i + "</td></tr>";
}
</script>
回答by olidem
Remark from 2019: I was struggling for hours, had an image in my header
2019 年的评论:我挣扎了几个小时,我的标题中有一张图片
<table>
<thead>
<tr>
<td>
<img ...>
</td>
which was only showing on first page.
只显示在第一页上。
Cause:Chrome adds a style @media print { img { page-break-inside: avoid !important; }?}
原因:Chrome 添加了样式@media print { img { page-break-inside: avoid !important; }?}
This was causing the image not to show on page 2 and on!
这导致图像未显示在第 2 页及以上!
Solution:So just insert a rule
解决方案:所以只需插入一条规则
@media print { thead img { page-break-inside: auto !important; }?}
to deactivate this browser specific rule.
停用此浏览器特定规则。
回答by Manny
for in-company browser based systems, i advice users to use firefox or IE instead;for websites intended for the public, i think we can't really do anything about it if users user chrome or browsers with similar limitations (opera also)
对于基于公司内部浏览器的系统,我建议用户改用 firefox 或 IE;对于面向公众的网站,我认为如果用户使用 chrome 或具有类似限制的浏览器(opera 也是如此),我们将无能为力