我想在每个打印的页面上重复表格的标题,但是Google
Chrome浏览器似乎不太支持该<thead>
标签…是否可以解决此问题?我正在使用Google Chrome v13.0.782.215。
该表代码非常简单……一点都不花哨:
<!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>
欢迎对此有任何见识。
更新2017年3月22日:重复表头终于在Chrome中实现了!(实际上,我认为它们是在一段时间之前实现的。)这意味着您可能不再需要此解决方案。只需将列标题放在<thead>
标签中就可以了。仅在以下情况下使用以下解决方案:
解决方案(已淘汰)
下面的代码演示了我发现的多页表格打印的最佳方法。它具有以下功能:
…以及以下已知限制:
JS运行后,无法(轻松)动态更改表
编码
<!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>
它是如何工作的(如果您不在乎,请继续阅读;上面您需要的一切。)
根据@Kingsolmn的要求,以下说明了此解决方案的工作方式。它没有涵盖并不是严格要求的JavaScript(尽管它确实使此技术更易于使用)。相反,它专注于生成的HTML结构和关联的CSS,这才是真正的魔术。
这是我们将要使用的表:
<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>
(为了节省空间,我只给了它3个数据行;显然,一个多页表通常会有更多行)
我们需要做的第一件事是将表拆分为一系列较小的表,每个表都有自己的列标题副本。我称这些较小的表为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>
fauxRows本质上是原始表的克隆,但每个表仅包含一个数据行。(不过,如果您的表有标题,则只有顶部的fauxRow才应包含它。)
接下来,我们需要使fauxRows 牢不可破。这意味着什么?(请注意-这可能是分页符处理中最重要的概念。)“牢不可破”是我用来描述无法在两个页面之间分割的内容块的术语*。当在此类块所占据的空间内发生分页符时,整个块将移至下一页。(请注意,我在这里非正式地使用了“块”一词;我并不是专门指块级元素。)此行为有一个有趣的副作用,我们稍后会加以利用:它可以公开内容由于分层或溢出最初被隐藏。
通过应用以下两个CSS声明,我们可以使fauxRows坚不可摧:
page-break-inside: avoid;
display: inline-table;
我通常同时使用这两种方法,因为第一种是为此目的而制成的,第二种是在较旧/不兼容的浏览器中起作用的。不过,在这种情况下,为简单起见,我将坚持使用page-break属性。请注意,添加此属性后,您将看不到表格外观的任何变化。
<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>
现在,fauxRows是不可破坏的,如果在数据行中发生了分页符,它将移至下一页及其附加的标题行。因此,下一页将始终在顶部具有列标题,这是我们的目标。但是,表现在看起来很奇怪,带有所有额外的标题行。为了使它再次看起来像一张普通表,我们需要隐藏额外的标题,使它们仅在需要时才会出现。
我们要做的是将每个fauxRow放入带有的容器元素中overflow: hidden;,然后将其向上移动,以使标头被容器的顶部剪裁。这还将把数据行移回一起,使它们看起来是连续的。
您的第一个直觉可能是对容器使用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>
请注意表格标记上方的CSS。我添加它的原因有两个:首先,它防止父表在fauxRows之间添加空白;其次,它使标头高度可预测,这是必需的,因为我们没有使用JavaScript来动态地计算它。
现在我们只需要向上移动fauxRows,我们将使用负边距进行处理。但这并不像您想的那么简单。如果我们直接向fauxRow添加负边距,则当fauxRow碰到下一页时,它将保持有效,从而导致页眉被页面顶部裁剪。我们需要一种方法来消除负利润。
为此,我们将在每个fauxRow的第一个之后插入一个空的div,并向其添加负边距。(第一个fauxRow会被跳过,因为它的标题应该始终可见。)由于页边距在单独的元素上,因此它不会跟随fauxRow到下一页,并且标题也不会被剪切。我称这些为空的divs 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>
运行代码段展开摘要
就是这样,我们完成了!在屏幕上,该表现在看起来应该是正常的,顶部只有一组列标题。在打印中,它现在应该具有正在运行的标题。
如果您想知道为什么我们使用父表而不是一堆容器div,那是因为Chrome / webkit有一个错误,该错误会导致div封闭的不可破坏块将其容器携带到下一页。由于headerHider也位于容器中,因此不会像预期的那样被遗忘,这会导致标题被剪切。仅当不可破坏的块是div中具有最高非零高度的元素中的最高元素时,才会发生此错误。
在编写本教程时,我确实发现了一种解决方法:您只需要height: 0;在headerHider上进行显式设置,并为其提供一个非零高度的空子div。然后,您可以使用div容器。不过,我仍然更喜欢使用父表,因为它已经过更彻底的测试,并且通过将fauxRows绑回到一个表中,在某种程度上可以挽救语义。
编辑:我刚刚意识到JavaScript生成的标记稍有不同,因为它将每个fauxRow放在单独的容器表中,并为其分配“ fauxRow” className(容器)。这是页脚支持所必需的,我打算有一天要添加它,但从未这样做。如果要更新JS,我可能会考虑切换到div容器,因为使用表的语义理由不适用。
*
在一种情况下,不可破坏的块可以分为两页:当它超出可打印区域的高度时。您应该尝试避免这种情况;实际上,您是在要求浏览器执行不可能的事情,并且它会对输出产生一些非常奇怪的影响。
问题内容: 在CSS中使用@page内的属性是否可以说,如果表分布在多个页面上,则应在每个页面上重复表头(th)? 问题答案: 这就是THEAD元素的用途。官方文档在这里。
问题内容: 亲爱的所有人,我尝试过CSS位置:固定属性,但是它在Firefox和IE(适用于IE6的hack)上可以正常工作,但对于Chrome则根本不起作用。我以为Chrome是最新的,将非常容易地支持它,但事实并非如此。我尝试了, 再次在IE和Firefox中运行,但在Chrome中出现了问题。请任何人对此有替代解决方案。 问题答案: 这是我使用的代码。注意我将html和正文高度都设置为100
我想从web浏览器的Brother标签打印机打印标签。我知道DYMO有一个JavaScript框架,可以使从浏览器打印变得简单。但我有一个兄弟标签打印机的客户,所以我需要使它工作。 我一直在做一些测试和搜索,令人惊讶的是,关于这个主题的信息如此之少。 到目前为止,我唯一成功使用的浏览器是谷歌Chrome,因为它似乎不打印页眉和页脚。我已经安装了打印机/驱动程序,并创建了尺寸为62 x 29mm的自
问题内容: 我已经阅读了很多有关打印页码的网站,但是当我尝试打印html页面时,仍然无法显示它。 接下来是CSS代码: 我试图把这个页面规则放进去 在其外部,尝试将其放入中,但没有任何帮助使我在页面上显示页码。我尝试使用FireFox和Chrome(您知道基于WebKit的浏览器)。我认为问题出在我的HTML或CSS代码中。 有人可以告诉我一个在具有多个页面的大html页面中实现此规则的示例吗?我
问题内容: 我已经在SO和其他一些网站上以几种不同的方式问过这个问题,但是其中大多数要么太具体,要么已经过时。我希望有人可以在这里提供明确的答案,而不必担心猜测。 当有人在浏览器中打印时,是否可以使用CSS或javascript更改默认打印机设置?当然,“从他们的浏览器打印”是指某种形式的HTML,而不是PDF或其他依赖于插件的mime类型。 请注意: 如果某些浏览器提供了此功能,而另一些却不提供
现在如何将此保存到浏览器。