Printing html tables, preventing rows from spanning multiple pages

后端 未结 2 550
说谎
说谎 2020-12-19 23:52

I generate html programmatically in order to have it rendered nicely for printing.

I have to print tables that may span several pages. This poses some challenges suc

相关标签:
2条回答
  • 2020-12-20 00:22

    Another solution to this problem that does not depend on fixed column widths is to wrap each cell's content in a display:block element and set this to page-break-inside: avoid. If you don't want to alter the HTML in the first place, you can alter the DOM dynamically on load. As I'm lazy, I'm using jQuery in the following example:

    <!DOCTYPE html><html><head><meta charset="utf-8"><style type="text/css">
    th, td { border: 1px solid #aaa; }
    @media print {
      td hack {
        display: block;
        page-break-inside: avoid;
      }
    }
    </style>
      <script src="https://code.jquery.com/jquery-3.5.0.js"></script>
      <script>
        window.addEventListener('load', function() {
            $( "td" ).wrapInner( "<hack></hack>" );
        })  
      </script>
    </head>
    <body>
    <table>
      <tr><th>A</th><th>B</th><th>C</th></tr>
      <tr><td>more text<br>1<br>2<br>3<br>4<br>5<br></td><td>more text</td><td>more text</td></tr>
      <tr><td>1 adasd<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1asd<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>xsdsdfsf</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2 asda asdas<br>3<br>4<br>5<br>6<br></td><td>xasdada</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4 asdasd <br>5<br>6<br></td><td>x</td><td>x</td></tr>
    </table>
    </body></html>
    

    The result will look a bit different:

    You see the following issues:

    • the row already starts at the previous page (which can be a seen as an indication for the table is still continuing)
    • the content of columns B and C is vertically centred according to the total height of the row spanning both pages so it appears to be top aligned towards the highest cell in column A

    But the solution does work with WebKit browsers and still renders as a normal table.

    0 讨论(0)
  • 2020-12-20 00:27

    Adding

    td, th {
      width: 10000px;
    }
    

    inside @media print { } did the trick to make the example code work.

    Now the printed columns are properly aligned again, and each row stays on a single page, never spanning two pages.

    Works in current versions of Webkit (Safari), FF and Chrome (all tested on macOS only).

    Caveat:

    Unfortunately, the above is not fool proof. It only works in this example because the cells in each row have the same width.

    Once those widths are random, an over-reaching pixel width like 10000px is messing up the columns again.

    The only solution I found around this is to provide actual widths that are to be used. Since this is for printing, and since I know that I want to print to a specific paper format (e.g. DIN A4 or US Letter), I can specify the column width precisely with certainty.

    So, while this solution is not a good one for a web page view in a browser on-screen, where the total width can vary, it's a good solution for printing, as long as the target print size can be predicted.

    Here is the complete html code, setting the column widths to 4cm, 2cm and 3cm:

    <!DOCTYPE html><html><head><meta charset="utf-8"><style type="text/css">
    th, td { border: 1px solid #aaa; }
    @media print {
      table, tr, td, th {
        page-break-inside: avoid;
      }
      tr {
        display: block;
        page-break-before: auto;
      }
      td:nth-child(1), th:nth-child(1) {
        width: 4cm;
      }
      td:nth-child(2), th:nth-child(2) {
        width: 2cm;
      }
      td:nth-child(3), th:nth-child(3) {
        width: 3cm;
      }
    }
    </style></head>
    <body>
    <table>
      <tr><th>A</th><th>B</th><th>C</th></tr>
      <tr><td>more text<br>1<br>2<br>3<br>4<br>5<br></td><td>more text</td><td>more text</td></tr>
      <tr><td>1 adasd<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1asd<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>xsdsdfsf</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4<br>5<br>6<br></td><td>x</td><td>x</td></tr>
      <tr><td>1<br>2 asda asdas<br>3<br>4<br>5<br>6<br></td><td>xasdada</td><td>x</td></tr>
      <tr><td>1<br>2<br>3<br>4 asdasd <br>5<br>6<br></td><td>x</td><td>x</td></tr>
    </table>
    </body></html>
    
    0 讨论(0)
提交回复
热议问题