Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

css - Printing html tables, preventing rows from spanning multiple pages

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 such as preventing cell contents to spread over two pages like this:

enter image description here

I found a solution in this answer, which uses page-break-inside:avoid, along with this answer, which uses display: block for the <tr> elements in order to prevent them from getting split up vertically.

However, this also causes the rows not to vertically align with each other any more. How do I fix that?

Here's how it should look (and how the browser renders it on-screen):

enter image description here

And here's what it renders for printing:

enter image description here

How do I make the printout aligned, the samew as it's aligned on the screen, without having to lose the display: block ability to keep cells vertically intact at page breaks? It has to work in Webkit (Safari) on macOS.

Here's the complete html code. It spans two pages so that one can check whether individual cells appear half on one and half on the next page (which is not desired):

<!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;
  }
}
</style></head>
<body>
<table style="width:40%">
  <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<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>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>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>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>
</table>
</body></html>

Update:

I also tried this solution which uses div instead of table. This gives slightly different results when printing, but still bad (now the cell heights are wrong, too):

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...