Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid page break inside table row for wkhtmltopdf

I am generating pdf report from html page with one table.

I am using wkhtmltopdf for the purpose.

when pdf is generated it breaks anywhere in tr tag.

I want to avoid it .

like image 317
Mohammad Sadiq Shaikh Avatar asked Nov 22 '12 16:11

Mohammad Sadiq Shaikh


People also ask

How do I prevent page breaks within a table row?

Make sure all parent elements are display: block . Also consider overriding table , tr , td 's display styles with CSS grid for the print layout if you keep having issues with the table.

How do I avoid a page-break inside?

The page-break-inside property sets whether a page-break should be avoided inside a specified element. Tip: The properties: page-break-before, page-break-after and page-break-inside help to define how a document should behave when printed. Note: You cannot use this property on absolutely positioned elements.

How do I stop page breaks in HTML?

Syntax: page-break-inside: auto; avoid: It avoids a page break inside the element.


2 Answers

Update 17.09.2015: Check the version you are using: wkhtmltopdf 0.12.2.4 is said to fix the problem (I have not checked).


This is a known issue in wkhtmltopdf. The page breaking algorithm used by webkit (the WK in WKhtmltopdf) doesn't really work well for large tables. I suggest breaking the table down to smaller chunks that are more easily split to pages and using the css a lot:

table, tr, td, th, tbody, thead, tfoot {     page-break-inside: avoid !important; } 

Also have a look at the following wkhtmltopdf issues, they have interesting comments that discuss for example the table splitting problem. There is a JS solution that programmatically splits tables in 168 that might help you (I don't use it though).

  • https://code.google.com/p/wkhtmltopdf/issues/detail?id=168
  • https://code.google.com/p/wkhtmltopdf/issues/detail?id=9

Update 08.11.2013 There is much discussion about this in issue 168 linked above. Someone has managed to compile a version of wkhtmltopdf that supports better table breaking, but unfortunately it seems that it's not officially released and might contain other bugs. I don't know how to get it and I don't know how to compile on Windows, but anyone interested can check for example the comment here (see new update below).

Update 24.02.2014 You will be pleased to hear that in wkhtmltopdf 0.12 this feature among others has been greatly improved. However, wait for 0.12.1 and test thoroughly before starting to use any new version, it's still a little unstable although the new guys working on with antialize are doing a Great job (ashkulz rocks)! Keep updated at wkhtmltopdf.org and github. The google code site is obsolete and being slowly migrate.

like image 121
Joel Peltonen Avatar answered Sep 21 '22 22:09

Joel Peltonen


It is old post, but since i was wasting lot of time trying to find proper solution, i will put it here, maybe it will be useful to someone.

So from what i read, the problem with

page-break-inside: avoid 

is that it doesn't work. But actually if you set it on element that has display:block it works as expected (as noted somewhere in SO). so for simple structure of table css with

td div, th div{     page-break-inside: avoid; } 

and table structure

<table> .... <tr>     <td><div>some text</div></td>     <td><div>more text</div></td> </tr> .... </table> 

will work as expected.

I had bit more complicated case with rowspans, so the solution from above was breaking it to peaces, which wasn't desired effect. I solved it using divs for each rowspaned set of lines. My jquery js doing all the job:

$(window).load(function () {     var sizes = {};     $('#the_table tr:first th').each(function (a, td) {                  var w = $(td).width();         if (sizes.hasOwnProperty('' + a)) {             if (sizes['' + a] < w)                 sizes['' + a] = w;         }         else {             sizes['' + a] = w;         }     });      var tableClone = $('#the_table').clone();     $('#the_table').replaceWith('<div class="container"></div>');      var curentDivTable;     var cDiv = $('.container');     tableClone.find('tr').each(function (i, ln) {         var line = $(ln);         if (line.hasClass('main_row')) {             var div = $('<div class="new-section"><table><tbody>')             currentDivTable = div.find('tbody');             cDiv.append(div);                        }         currentDivTable.append(line);     });     //optional - maybe in % its better than px     var sum = 0;     $.each(sizes, function (a, b) {         sum += b;     });     var widths = {};     $.each(sizes, function (a, b) {         var p = Math.ceil(b * 100 / sum);         widths['' + a] = p + '%';     });     //setup     $('.container table').each(function (a, tbl) {         $(tbl).find('tr:first td, tr:first th').each(function (b, td) {             $(td).width(widths['' + b]);         });         $(tbl).addClass('fixed');     }); }); 

css:

div.new-section {     page-break-inside: avoid; } .container, .new-section, .new-section table.fixed{     width: 100%; }  .new-section table.fixed{     table-layout:fixed; } 

I don't know if everything is needed and I don't think its perfect, but it does the job. Tested on chrome only

like image 22
Internal Server Error Avatar answered Sep 19 '22 22:09

Internal Server Error