Google Chrome在打印的页面上重复表格标题
我希望每张打印的页面都有我的表格标题,但似乎Google Chrome不支持那个标签。有没有办法解决这个问题? 我正在使用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>
任何对此的洞察力都是值得欢迎
我相信这是Chrome中的一个错误 。
更新2017-03-22:重复的表头已经在Chrome中实现了! (实际上,我认为他们是在一段时间之前实现的。)这意味着你可能不再需要这个解决scheme了; 只要把你的列标题放在一个<thead>
标签中,你就可以全部设置。 只有在以下情况下才使用以下解决scheme:a)您在Chrome的实现中遇到了显示停止的错误,b)您需要“奖励function”,或者c)您需要支持一些仍然不支持重复标题的古怪的浏览器。
解决scheme(过时)
下面的代码演示了我发现的多页表格打印的最佳方法。 它具有以下特点:
- 列标题在每个页面上重复
- 无需担心纸张大小或多less行将适合 – 浏览器自动处理一切
- 分页符只在行之间发生
- 单元格边界总是完全closures
- 如果在表格顶部附近出现分页符,则不会留下没有附加数据的孤立标题或列标题(问题不仅限于Chrome)
- 在Chrome中运行! (以及其他基于Webkit的浏览器,如Safari和Opera)
…以及以下已知的限制:
- 只支持1
<thead>
(这显然是你允许拥有的最多的) - 不支持
<tfoot>
(尽pipeChrome兼容的页脚在技术上是可行的 ) - 仅支持顶部alignment的
<caption>
- 表格不能有顶边或底边; 在表格上方或下方添加空格,插入一个空的div并在其上设置底部边距
- 任何影响高度的CSS尺寸值(包括
border-width
和line-height
)都必须在px
-
不能通过将宽度值应用到单独的表格单元来设置列宽度; 您应该让单元格内容自动确定列宽,或者根据需要使用
<col>s
设置特定的宽度 -
在JS运行之后,表不能(很容易)dynamic地改变
代码
<!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>
它是如何工作的 (如果你不在乎,不要再读了,你需要的只是上面的内容。)
Per @ Kingsolmn的请求,下面是这个解决scheme如何工作的解释。 它不包括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>
现在有可能使用jQuery打印铬…请试试这个代码(我很抱歉忘记谁是这个代码的创build者之前我修改 – 而我的英文不好: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>
这是Webkit,Blink和Vivliostyle中尚未提供的增强function,而不是其他更多“面向打印的格式化程序”(Firefox,IE)。
你可以从谷歌浏览器版本4(这里是6年前和45年前!)检查问题 ,在那里我们可以欣赏它最近有一个所有者(2016年2月),谁似乎正在处理它。
在W3中也曾经有过一些谈话,我们可以欣赏它的用处:
由于在碎片中断上重复表格页眉和页脚通常是有用的,所以我build议我们制定一个规范性要求,并且当表跨越中断时,UA必须重复页眉/页脚行。
同时,来自@DoctorDestructo和@theFredzx的JS和Jquery代码对于不使用Firefox和IE(其中大多数)的用户非常有用。
首先要注意包含这个特性的新版本,应该在这里注意它,我们很多人会感激它。
从我的testing在铬设置display: table-row-group;
到thead停止问题发生。
例如,如果您尝试打印下面的样式,您将在每个页面的顶部看到数字,但是如果添加样式,则只会显示在ontext上。
<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>
对于公司内部基于浏览器的系统,我build议用户使用Firefox或者IE;对于面向公众的网站,如果用户使用chrome或者具有类似限制的浏览器,我认为我们不能做任何事情(歌剧也是)