15

I am generating a print report using table in layout. The page has multiple tbody inside a table; While Printing the page it requires a page-break-after each tbody

To do so, I have applied

@media print {
    tbody{
        page-break-after: auto;
        page-break-inside: avoid;
        border: none !important;
        margin-bottom: 20px !important;
    }
}

What is the issue?

  • while applying the style page-break-after to a tbody , page-break is not working see here

  • but when applying display:block to tbody, it gives desired result but the layout of table is being distorted after changing tbody display:table-row-group to display:block See Here

I want to break the page after tbody using page-break-after: auto;.

Scenario is given below

table

Suresh Karia
  • 17,550
  • 18
  • 67
  • 85
  • It is unclear what you want. First you say you want page break after each `tbody`, then you say you don’t. And if you set `display: block`, you *are* breaking table layout. Please focus on describing exactly what you want and how your best attempt (here apparently the *first* one) fails in doing that, and on which browser(s). – Jukka K. Korpela Jan 03 '15 at 09:42
  • I want page break while tbody display:table-row-group – Suresh Karia Jan 03 '15 at 11:04
  • Still not clear at all. Your code shows not attempt at forcing page breaks after `tbody` elements, only preventing page breaks inside them. Do you want that, or do you want a page break after each `tbody`? If the latter, what happens on which browser(s) when you try the obvious `page-break-after: always`? – Jukka K. Korpela Jan 03 '15 at 13:41

4 Answers4

20

This is a known problem. page-break properties apply only to block-level elements.

This is why you are not getting page-breaks on your tbody. When you explicitly change tbody from its display: table-row-group to display: block, then the page-breaks will start applying. But, then this will break the layout of your table.

As per specs: http://www.w3.org/TR/CSS21/page.html#page-break-props

User Agents must apply these properties to block-level elements in the normal flow of the root element. User agents may also apply these properties to other elements, e.g., 'table-row' elements

Although, the specs say that user agents may also apply these properties on table-row, the word "may" plays its role and the behaviour is not uniform across implementations.

Solution:

Apply page-break to a block-level pseudo-element on your tbody instead of directly applying it to tbody.

Like this:

tbody::after {
    content: ''; display: block;
    page-break-after: always;
    page-break-inside: avoid;
    page-break-before: avoid;        
}

Here is your working fiddle: http://jsfiddle.net/abhitalks/DTcHh/3054/

Also, note that this alone will not solve all of your problems. You must carefully define your page-context and appropriate margins and dimensions to suit your use-case.

This will give you a start:

@page {
    size: A4;
    margin: 0;
}
@media print {
    html, body {
        width: 210mm;
        height: 297mm;
    }
    ...
}

Here is a snippet with a very simple example to try it out. To test, check the print preview, there should be two page-breaks, one after each tbody.

Snippet:

table, th, td { border: 1px solid gray; border-collapse: collapse; }
th, td { padding: 8px; }
tbody:first-of-type { background-color: #eee; }

@page {
    size: A4;
    margin: 0;
}
@media print {
    html, body {
        width: 210mm;
        height: 297mm;
    }
    tbody::after {
        content: ''; display: block;
        page-break-after: always;
        page-break-inside: avoid;
        page-break-before: avoid;        
    }
    
  
}
<div> 
    <a href="#" onClick="window.print();">Print</a>
</div>
<hr />
<table>
    <thead>
  <tr>
   <th>Head 1</th>
   <th>Head 2</th>
   <th>Head 3</th>
  </tr>
    </thead>
 <tbody>
  <tr>
   <td>Row 1 Cell 1</td>
   <td>Row 1 Cell 2</td>
   <td>Row 1 Cell 3</td>
  </tr>
  <tr>
   <td>Row 2 Cell 1</td>
   <td>Row 2 Cell 2</td>
   <td>Row 2 Cell 3</td>
  </tr>
 </tbody>
 <tbody>
  <tr>
   <td>Row 3 Cell 1</td>
   <td>Row 3 Cell 2</td>
   <td>Row 3 Cell 3</td>
  </tr>
  <tr>
   <td>Row 4 Cell 1</td>
   <td>Row 4 Cell 2</td>
   <td>Row 4 Cell 3</td>
  </tr>
 </tbody>
    <tfoot>
  <tr>
   <th>Foot 1</th>
   <th>Foot 2</th>
   <th>Foot 3</th>
  </tr> 
    </tfoot>
</table>

Disclaimer: I have tested it only against Chrome v39. You need to apply your own tests.

.

Abhitalks
  • 27,721
  • 5
  • 58
  • 81
  • How to apply page-break inside table body. Like table has huge amount of data and it needs 5 pages to be printed then how to apply pagebreak inside tbody? – Muneem Habib Jun 26 '15 at 06:37
  • 14
    It doesn't work, example http://jsfiddle.net/abhitalks/DTcHh/3054/ still breaks page on the middle of second tbody https://screencast.com/t/M5pzpMEIJq0j – Vedmant Jun 18 '18 at 08:40
0

I managed this problem by closing and opening a new table instead of grouping rows in <tbody>. In table css you can put:

display: block;

and page-break works there without breaking layout of the table.

GuZzie
  • 974
  • 1
  • 6
  • 23
Pawel
  • 1
0

I solved it wrapping the table

<div style="display: block; break-inside: avoid">
   <table>
      <tr>
         <td>
            Col 1
         </td>
         <td>
            Col 2
         </td>
      </tr>
   </table>
   <p style="page-break-after: always;"> </p>
</div>
-1

This is possible by doing this:

tbody {
    display: block;
    width: 100%;
    page-break-after: always;
    page-break-inside: avoid;
    page-break-before: avoid;
}
Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
Raisul Islam
  • 1,161
  • 1
  • 9
  • 18