1

I'm struggling to print a dynamic HTML table by using Chrome and Firefox. I'm working on a project using Yii framework and in one of my view I create a HTML table that only fits on multiple pages and should be printed. Height of table rows may vary depending on content.

I'm using THEAD and TBODY elements in my table and I made relevant grouping in my print media CSS. To initiate print dialogue I'm using window.print() JavaScript command .

I read somewhere that Chrome can't divide multiple page long tables properly even if you set page-break-after and page-break-before parameters in your CSS which seems to be true. Firefox can handle theses commands however table header and table content overlap starting from the second page.

Do I need to change my code and draw DIVs instead of table or maybe I should write a JavaScript to split content based on table height?

Please find herewith my CSS for media print:

@page {
    margin-top: 1cm;
    margin-right: 1cm;
    margin-bottom:2cm;
    margin-left: 2cm;
    size: landscape;
}
.form, h1, .summary, .navbar-inner {display: none;}

table { page-break-after:auto;}
tr    { page-break-inside:avoid;}
td    { page-break-inside:auto;}
thead { display:table-header-group; }
tbody { display:table-row-group;}
g0m3z
  • 691
  • 1
  • 12
  • 25

2 Answers2

1

Based on my findings it seems webkit based browsers (e.g.: Chrome) can't handle pagination of long tables even if you set your media print css properly. Furthermore I would say that almost all browsers handles print media style sheet on a different way.

It would be good to see a general solution for this, a standard I mean. I know this is what CSS is for but it doesn't seem to work in this case, or each browser development team interprets it on a different way.

In my case I solved the problem with a JQuery. Someone referred to this JQuery in a different post, but in my case height of some cells are changing dynamically, thus I couldn't use this query, however it led me to a solution.

Just in a nutshell:

I divide my table to a header and data blocks by creating separate tables for those. So, I have a header (a table) and several data blocks (other tables). I print them to the screen one under the other, thus on the screen it seems as a long table.

Then I create an empty table on the page. This is required for the JQuery.

Once everything printed to the screen I run a JQuery which splits my table to pages by looping through all blocks and move each blocks from the original table to my empty table. If the height of X number of blocks reaches the height of the page then it adds a pageberak and a header again and continues looping through on the remaining blocks. At the end my original table becomes empty and my empty table filled up with headers, data blocks and pagebreaks.

My generated HTML page contains the following tables:

<table class='mainheader'>
    .
    HEADER
    .
</table>
<table class='body_block'>
    .
    DATA
    .
</table>
<table class='body_block'>
    .
    DATA
    .
</table>
<table class='body_block'>
    .
    DATA
    .
</table>
    .
    .
    .


<table class='tmp_table'>
</table>

My JQuery:

<script type="text/javascript">
    var tableHeight = 0;
    var pagebreaker = $('<div style="display: block; page-break-before: always;"></div>');
    var header = $('.mainheader');
    $('.body_block').each(function()
    {
        if ((tableHeight + $(this).height()) >= 600){ // I use a 600px height page
            $('.tmp_table').append(pagebreaker.clone());
            $('.tmp_table').append(header.clone());
            tableHeight = 0;
        }
        tableHeight += $(this).height();
        $(this).appendTo('.tmp_table');
    });
</script>
g0m3z
  • 691
  • 1
  • 12
  • 25
0

I've posted a solution that addresses the problems described in this post, and does not involve trying to predict how many rows will fit on a page (which is impossible since there is no way to know what paper size the user is using). That solution is compatible with all modern browsers, including the webkit-based ones (Chrome, Safari, Opera). For the non-webkit-based browsers (Firefox and Internet Explorer), there's actually a simpler solution: just set page-break-inside: avoid; on the <tr> elements.

Community
  • 1
  • 1
DoctorDestructo
  • 4,166
  • 25
  • 43