让 Google Chrome 在打印页面上重复表格标题

Posted

技术标签:

【中文标题】让 Google Chrome 在打印页面上重复表格标题【英文标题】:Having Google Chrome repeat table headers on printed pages 【发布时间】:2011-11-04 21:21:16 【问题描述】:

我想为每个打印页面重复我的表格标题,但 Google Chrome 似乎不支持 <thead> 标记...有没有办法解决这个问题?我使用的是谷歌浏览器 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 >...</td>
              <td >...</td>
              <td >....</td>
              <td >...</td>
              <td >...</td>
           </tr>
           <tr class="row1">
              <td >...</td>
              <td >...</td>
              <td >....</td>
              <td >...</td>
              <td >...</td>
           </tr>
           ....
       </tbody>
   </table>
   </body>
</html>

欢迎对此的任何见解。

【问题讨论】:

您可以检查 Chrome 错误跟踪器以查看这是否是错误 @Yi Jiang:我做过,而且似乎这是一个长期存在的问题,从未解决过......真的很沮丧 如果您关心这个错误在 Chrome 中得到修复,请使用下面的链接转到错误报告并点击左上角的星号“加星标”。 【参考方案1】:

更新 2017-03-22:重复表头终于在 Chrome 中实现了!(实际上,我认为它们是前一段时间实现的。)这意味着您可能不需要这个解决方案不再;只需将列标题放在&lt;thead&gt; 标记中,您就应该准备就绪。仅在以下情况下使用以下解决方案:

您在 Chrome 的实现中遇到了显示停止的错误, 您需要“奖励功能”,或者 您需要支持一些仍然不支持重复标题的古怪浏览器。

解决方案(已过时)

下面的代码演示了我发现的用于多页表打印的最佳方法。它具有以下特点:

列标题在每一页上重复 无需担心纸张大小或可容纳多少行 - 浏览器会自动处理所有内容 分页只发生在行之间 单元格边框始终完全闭合 如果在表格顶部附近出现分页符,它不会留下没有附加数据的孤立标题或列标题(此问题不仅限于 Chrome) 在 Chrome 中工作! (以及其他基于 Webkit 的浏览器,例如 Safari 和 Opera)

...以及以下已知限制:

仅支持 1 个&lt;thead&gt;(这显然是你最多的allowed to have) 不支持 &lt;tfoot&gt;(尽管与 Chrome 兼容的运行页脚为 technically possible) 仅支持顶部对齐&lt;caption&gt; 表格不能有顶部或底部margin;要在表格上方或下方添加空白,请插入一个空 div 并在其上设置下边距 任何影响高度的 CSS 大小值(包括 border-widthline-height)都必须在 px

无法通过将宽度值应用于单个表格单元格来设置列宽;您应该让单元格内容自动确定列宽,或者在需要时使用&lt;col&gt;s 设置特定宽度

在 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 牢不可破。那是什么意思? (注意——这可能是分页处理中最重要的概念。)“牢不可破”是我用来描述不能在两页之间拆分的内容块的术语*。当在这样一个块占用的空间内发生分页时,整个块移动到下一页。 (请注意,我在这里非正式地使用了“阻止”这个词;我不是专门指的是block level elements。)这种行为有一个有趣的副作用,我们稍后会用到on:它可以暴露最初由于分层或溢出而隐藏的内容。

我们可以通过应用以下任一 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 之后的每个 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>

就是这样,我们完成了!在屏幕上,表格现在应该看起来正常,顶部只有一组列标题。在打印中,它现在应该有正在运行的标题。

如果您想知道为什么我们使用父表而不是一堆容器 div,那是因为 Chrome/webkit 存在一个错误,导致 div 封闭的不可破坏块将其容器携带到下一页。由于 headerHider 也在容器中,因此它不会像预期的那样被遗忘,这会导致标题被剪裁。仅当不可破坏块是 div 中高度非零的最顶部元素时才会发生此错误。

我在编写本教程时确实发现了一种解决方法:您只需在 headerHider 上显式设置 height: 0; 并为其提供一个高度非零的空子 div。然后你可以使用一个 div 容器。不过,我仍然更喜欢使用父表,因为它已经过更彻底的测试,并且通过将 fauxRows 重新组合到一个表中,它在一定程度上挽救了语义。

编辑:我刚刚意识到 JavaScript 生成的标记略有不同,因为它将每个 fauxRow 放在一个单独的容器表中,并将“fauxRow”类名分配给它(容器)。这将是页脚支持所必需的,我打算在某天添加但从未添加。如果我要更新 JS,我可能会考虑切换到 div 容器,因为我使用表的语义理由不适用。

* 在一种情况下,一个不可破坏的块可以在两页之间分割:当它超过可打印区域的高度时。你应该尽量避免这种情况;您实际上是在要求浏览器完成不可能的事情,它会对输出产生一些非常奇怪的影响。

【讨论】:

@DoctorDestructo 我试图实现这个解决方案,它确实避免了在一行内分页,但我最终把所有列都搞砸了,就像这张图片:s11.postimg.org/uyhoktapv/error.jpg你能帮我吗解决这个问题?提前致谢! @delphirules 确保没有将宽度值应用于表中的任何 &lt;td&gt;&lt;th&gt; 元素。只有两种有效的方法来设置列宽:1)让单元格内容自动设置它,或者2)使用&lt;col&gt;元素。如果这不是问题,那么我可能必须查看您的表格 html(在运行所需的 js 函数之前)来诊断它。 @delphirules 如果您的表格应用了顶部填充,则可能会导致您描述的行为。最好的解决方法是去掉顶部填充,而是为表格上方的元素添加底部边距。 (事实上​​,在打印时,通常最好将底部边距用于垂直空白)。 @Kingsolmn yw!下面简单解释一下它的工作原理:js 将你的表拆分为一系列单行子表,每个子表都有自己的一组列标题。负边距将每个子表部分缩回其容器中,隐藏标题。边距的实现方式是,如果子表被分页符撞到下一页,它不会延续。因此,每个页面上的第一个子表都会有可见的标题。 @Kingsolmn 我考虑过在这篇文章中添加更详细的解释。我什至考虑过添加页脚支持。但是,令人惊讶的是,Chrome 的错误跟踪器显示有人实际上正在尝试fix this problem。如果他们成功了,我怀疑这个问题会得到更多的意见。【参考方案2】:

我相信这是 Chrome 中的 bug。

【讨论】:

你是对的......在遇到您提供的相同链接后,我已经放弃了在 Chrome 上按预期工作 这实际上是一个bug in chromium报告于2008-02-07。我们不应该指望它会很快得到修复。 截至 2016 年 2 月,它似乎得到了一些爱:2016 年 2 月 4 日 #34 robho...@gmail.com 我正在为此努力。 现在已修复。 在 Chrome 79.0.3945.130 上似乎不适合我【参考方案3】:

现在可以使用 jQuery 在 chrome 中打印....请尝试此代码(我很抱歉在我修改之前忘记了此代码的创建者 - 而且我的英语不好 :D 呵呵)

            <!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>

【讨论】:

太棒了...我会在有时间的时候检查一下并报告。虽然我已经从这个问题继续前进 看起来不错,但在我的情况下,我使用的是行跨度(标题单元格跨越多个 tr。我建议使用自定义类来标记切割表格的位置。【参考方案4】:

这是一项在 Webkit、Blink 和 Vivliostyle 中仍然不可用的增强功能,而不是在其他更“面向打印的格式化程序”(Firefox、IE)中。

您可以查看issue for Google Chrome since version 4 here (6 years and 45 versions ago!),我们可以在其中了解到它最近(2016 年 2 月)有一个所有者,他甚至似乎正在研究它。

一些谈话has been also held in the W3,我们可以欣赏对它有用性的关注:

由于重复表格页眉和页脚 碎片中断通常是一个有用的东西,我建议我们做一个 规范要求,并说 UA 必须重复页眉/页脚行 当一个表跨越一个休息时。

与此同时,@DoctorDestructo 和 @thefredzx 的 JS 和 Jquery 代码对我的用户(大部分)不使用 Firefox 或 IE 非常有用。

第一个知道包含此功能的新版本的人应该在这里注意到它,我们中的许多人会很感激。

【讨论】:

看起来您的 Chrome 错误链接指向 W3 讨论(有趣的阅读,顺便说一句)。错误是here。【参考方案5】:

从我在 chrome 设置 display: table-row-group; 中的测试到 thead 停止了问题的发生。

例如,如果您尝试在没有样式的情况下打印以下内容,您将在每页顶部看到数字,但如果您添加样式,它只会出现在上下文菜单上。

<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>

【讨论】:

【参考方案6】:

2019 年的备注: 我挣扎了好几个小时,我的标题中有一张图片

<table>
 <thead>
    <tr>
      <td>
        <img ...>
      </td>

只显示在第一页。

原因: Chrome添加样式@media print img page-break-inside: avoid !important;  

这导致图像在第 2 页及以后不显示!

解决方案: 所以只需插入一条规则

@media print  thead img  page-break-inside: auto !important;  

停用此浏览器特定规则。

【讨论】:

【参考方案7】:

对于公司内部基于浏览器的系统,我建议用户改用 firefox 或 IE;对于面向公众的网站,我认为如果用户使用 chrome 或具有类似限制的浏览器(opera也)

【讨论】:

以上是关于让 Google Chrome 在打印页面上重复表格标题的主要内容,如果未能解决你的问题,请参考以下文章

Google Chrome 上的打印预览行为不同

当我在 Chrome 和 IE 上打印时如何修复和重复每个页面底部的内容

Google Chrome 打印分页符

Div 未在 Google chrome 中显示(在 Firefox 中显示)[重复]

如何在 Chrome 中的每个打印页面上打印部分网页(标题)

在 Chrome 上打印 Bootstrap 表时出现错误