How to apply CSS page-break to print a table with lots of rows?
Asked Answered
S

11

100

I have a dynamic table in my web page that sometimes contains lots of rows. I know there are page-break-before and page-break-after CSS properties. Where do I put them in my code in order to force page breaking if needed?

Saragossa answered 3/1, 2012 at 12:59 Comment(0)
G
171

You can use the following:

<style type="text/css">
   table { page-break-inside:auto }
   tr    { page-break-inside:avoid; page-break-after:auto }
</style>

Refer the W3C's CSS Print Profile specification for details.

And also refer the Salesforce developer forums.

Gruber answered 3/1, 2012 at 13:6 Comment(10)
If you are trying this with a framework like bootstrap be aware that using something like .spanX (which styles with float) can disrupt page-break-* attributes, lost a lot of time myself to this little nuance.Crayfish
this works with UIWebView so I assume this will also work with Safari nowRobtrobust
David thanks for sharing solution to work with safari or charome as well. JonEasy you can use solution of David in case this solution doesnt work with Safari. @Maxence glad it helped. Sorry I was not active for few months so was not able to respond early.Gruber
Sorry, but I'm unable to see what solution David provided (I'm also having the issue of this not working)Fleda
in addition to @Crayfish about .spanX, <section> as wellRosner
This solution does not break multi-line cells cleanly between their cell borders, but breaks them up in the middle. I've found a solution, though, which works in all current browsers (Safari, FF and Chrome): https://mcmap.net/q/176463/-printing-html-tables-preventing-rows-from-spanning-multiple-pagesTennietenniel
this doesn't work for me on chrome, the only solution which worked was to wrap content on each td inside a div since page-break-inside appears to be only working on display: block elements,Aphorize
@Aphorize this answer was provided few years back, it may possible that it does not comply with newer versions of browser. but you may get some hint through it.Gruber
@HemantMetalia would this work on breaking for columns as well?Screwdriver
@HelenAraya this answer was provided few years back, it may possible that it does not comply with newer versions of browser. but you may get some hint through it.Gruber
Z
25

Wherever you want to apply a break, either a table or tr, you needs to give a class for ex. page-break with CSS as mentioned below:

/* class works for table row */
table tr.page-break{
  page-break-after:always
} 

<tr class="page-break">

/* class works for table */
table.page-break{
  page-break-after:always
}

<table class="page-break">

and it will work as you required

Alternatively, you can also have div structure for same:

CSS:

@media all {
 .page-break  { display: none; }
}

@media print {
 .page-break  { display: block; page-break-before: always; }
}

Div:

<div class="page-break"></div>
Zetland answered 17/10, 2012 at 12:49 Comment(3)
This only works if you know ahead of time exactly how many rows will fit on a page (since you have to declare the page breaks directly in your markup). This might be difficult (or impossible) if there's a possibility that the data in a table row might wrap to a second line. And what about multiple page sizes (A4 vs US Letter vs US Legal)?Gilbertogilbertson
This solution did not work for me when using multi-line cells and multiple columns. I found a solution to that, though: https://mcmap.net/q/176463/-printing-html-tables-preventing-rows-from-spanning-multiple-pages - It also deals with the issue @Gilbertogilbertson mentions.Tennietenniel
Couldn't get the breaking tr to work either in Chrome v64.Nevillenevin
C
16

I have looked around for a fix for this. I have a jquery mobile site that has a final print page and it combines dozens of pages. I tried all the fixes above but the only thing I could get to work is this:

<div style="clear:both!important;"/></div>
<div style="page-break-after:always"></div> 
<div style="clear:both!important;"/> </div>
Conquistador answered 28/6, 2013 at 22:11 Comment(1)
This is work in table if that html put between two TR tags ( CHROME ). This is NOT work in table if that html put between two TR tags ( FIREFOX ). In FileFox work CSS Rule-> table tr:nth-child(10) {page-break-after: always;page-break-inside: avoid;}Leanoraleant
A
8

Unfortunately the examples above didn't work for me in Chrome.

I came up with the below solution where you can specify the max height in PXs of each page. This will then splits the table into separate tables when the rows equal that height.

$(document).ready(function(){

    var MaxHeight = 200;
    var RunningHeight = 0;
    var PageNo = 1;

    $('table.splitForPrint>tbody>tr').each(function () {

        if (RunningHeight + $(this).height() > MaxHeight) {
            RunningHeight = 0;
            PageNo += 1;
        }

        RunningHeight += $(this).height();

        $(this).attr("data-page-no", PageNo);

    });

    for(i = 1; i <= PageNo; i++){

        $('table.splitForPrint').parent().append("<div class='tablePage'><hr /><table id='Table" + i + "'><tbody></tbody></table><hr /></div>");

        var rows = $('table tr[data-page-no="' + i + '"]');

        $('#Table' + i).find("tbody").append(rows);
    }
    $('table.splitForPrint').remove();

});

You will also need the below in your stylesheet

    div.tablePage {
        page-break-inside:avoid; page-break-after:always;            
    }
Autopilot answered 18/8, 2014 at 16:29 Comment(1)
Doesn't do anything when the table has one large row.Puckery
M
1

this is working for me:

<td>
  <div class="avoid">
    Cell content.
  </div>
</td>
...
<style type="text/css">
  .avoid {
    page-break-inside: avoid !important;
    margin: 4px 0 4px 0;  /* to keep the page break from cutting too close to the text in the div */
  }
</style>

From this thread: avoid page break inside row of table

Malia answered 18/10, 2017 at 22:19 Comment(1)
this works somewhat extent. Means its stop cutting data in row at bottom. Row its still cutting. but at least better than actual issueGlyptograph
S
1

When converting to PDF with SelectPdf I couldn't get a group of rows to stay together. Tried to put them in a <div style="break-inside: avoid;"> but that didn't work.

Nothing was working until I found this: https://mcmap.net/q/174043/-avoid-page-break-inside-row-of-table
Which made me rethink my logic and place the things I didn't want to split inside a <tbody>.

<table>
  <thead style="display: table-header-group;">
    <tr>
      <th></th>
    </tr>
  </thead>

-- Repeating content --
  <tbody style="break-inside: avoid;">
    -- First row from group --
    <tr>
      <td> Only shown once per group </td>
    </tr>

    -- Repeating rows --
    <tr>
      <td> Shown multiple times per group </td>
    </tr>
  </tbody>

This results in a table that has multiple <tbody> but that's something that is completely fine as many people use this exact pattern to group together rows.

Spectacular answered 21/4, 2022 at 10:33 Comment(0)
U
0

If you know about how many you want on a page, you could always do this. It will start a new page after every 20th item.

.row-item:nth-child(20n) {
    page-break-after: always;
    page-break-inside: avoid;
}
Unwashed answered 11/10, 2018 at 13:2 Comment(1)
That not working for me :( I am using CHOME 83.0.4103.116Leanoraleant
C
0

I eventually realised that my bulk content that was overflowing the table and not breaking properly simply didn't even need to be inside a table.

While it's not a technical solution, it solved my problem to simply end the table when I no longer needed a table; then started a new one for the footer.

Hope it helps someone... good luck!

Chalaza answered 1/4, 2020 at 7:35 Comment(0)
K
-1

Here is an example:

Via css:

<style>
  .my-table {
    page-break-before: always;
    page-break-after: always;
  }
  .my-table tr {
    page-break-inside: avoid;
  }
</style>

or directly on the element:

<table style="page-break-before: always; page-break-after: always;">
  <tr style="page-break-inside: avoid;">
    ..
  </tr>
</table>
Kane answered 3/1, 2012 at 13:9 Comment(1)
This successfully uses 4 pages for what is effectively a 2 page table and seems to have the same effect as no css in Safari (6) and Chrome (24).Favianus
C
-1

We tried loads of different solutions mentioned here and elsewhere and nothing worked for us. However we eventually found a solution that worked for us and for us it seems to somehow be an Angular issue. I don't understand why this works, but for us it does and we didn't need any page break css in the end.

@media print {
    ng-component {
        float: left;
    }
}

So just hoping this helps someone else as it took us days to fix.

Clein answered 10/11, 2022 at 9:51 Comment(0)
M
-5

You should use

<tbody> 
  <tr>
  first page content here 
  </tr>
  <tr>
  ..
  </tr>
</tbody>
<tbody>
  next page content...
</tbody>

And CSS:

tbody { display: block; page-break-before: avoid; }
tbody { display: block; page-break-after: always; }
Mosby answered 17/7, 2019 at 9:47 Comment(1)
Manually dividing the table to pages isn't a very good solution unless the content is something that should naturally be printed on separate pages (e.g. financial information printed one page per year.) You don't know beforehand how much content will fit on one printed page.Todd

© 2022 - 2024 — McMap. All rights reserved.