Mohammad Saberi
Mohammad Saberi

Reputation: 13166

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

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?

Upvotes: 102

Views: 293363

Answers (11)

Jon
Jon

Reputation: 69

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.

Upvotes: -1

Karolis Vaitkevicius
Karolis Vaitkevicius

Reputation: 340

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://stackoverflow.com/a/27209406/11747650
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.

Upvotes: 2

AdheneManx
AdheneManx

Reputation: 348

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!

Upvotes: 0

Joris
Joris

Reputation: 11

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

Upvotes: -5

quemeful
quemeful

Reputation: 9848

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

Upvotes: 0

Alan
Alan

Reputation: 10125

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

Upvotes: 1

Scotty Rogers
Scotty Rogers

Reputation: 161

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>

Upvotes: 16

Hemant Metalia
Hemant Metalia

Reputation: 30638

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.

Upvotes: 174

Aditya P Bhatt
Aditya P Bhatt

Reputation: 22071

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>

Upvotes: 25

Jay
Jay

Reputation: 910

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

Upvotes: 8

tomthorgal
tomthorgal

Reputation: 525

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>

Upvotes: -1

Related Questions