19
votes

Does anyone have a link to an article or working example of repeating page headers/footers from Chrome specifically?

Background:
I've spent days on this with no luck, there are several Stack proposed solutions but none seem to work (in Chrome). Since we use Chrome at work I've only tested there, so a lot these below say Chrome just can't do it, but maybe I overlooked something?

I tried these Stack links (..and many more):

Print footer on every printed page from website, across all browsers (Chrome)

Is there a way to get a web page header/footer printed on every page?

How to use HTML to print header and footer on every printed page of a document?

Creating page headers and footers using CSS for print

If I can't, use repeating header/footers ...then my next idea is to count my rows in my clone object and have it break at a max number, create a new page (forced height) and start the loop again in another page in another div.

I truly appreciate any suggestions on running header/footer solution as the whole point to my app was the finished printed proposal.

5
Repeating table headers on printed pages was fixed on Chrome on Jun 5, 2016. I have the version 51.0.2704.103 on Mac OS X and it works.Ricardo

5 Answers

25
votes

Ok, no takers on this one, so with a few more days of looking around and choosing not to write my own solution, here is what I found.

At the very bottom of a Stack post with no votes and no comments was this lonely little link: http://welcome.totheinter.net/columnizer-jquery-plugin/#comment-53243

This thing is awesome, it's designed to handle wide pages of content and format them into columns like a newspaper. It handles page breaks especially well and is quite flexible.

In my case, I needed a single column (width of the page) and repeating headers and footers. I used Example 10 as my base:http://welcome.totheinter.net/autocolumn/sample10.html

I simply added the link to the plug in, changed the necessary IDs and classes to suit my page, and made some minor CSS changes to heights and widths and I was able to print multi-page content with repeating headers and footers in Google Chrome! (my company's preferred browser)

TIPS:

  • One little CSS trick, I made the content div MIN-HEIGHT set so it pushed the footer down on short pages. (Don't do this if you want the user to have the option of portrait or landscape). My final print is fixed so this was great for me.

  • I tested different heights on content to see how it breaks the content, it was smooth everytime.

I did try to post my final example in JsBin and Fiddle, but it ran an error each time.

So again, Example 10 above is a great place to start as it shows before and after.

Here is my final with variable height content and repeating Headers and Footers: (this is the view when I click the browser Print Link/Button in Chrome ) enter image description here

UPDATE 7/2014: Once again Chrome is the bane of my existence with print issues. I saw the comment below about the link that I provided. He's right, it renders correctly but the print view is incorrect. Sorry about that, but it's still a good example to play with to learn the settings.

I am still using this solution, IT DOES work, but you have to adjust the CSS and the JS var for body content size. The sizing combinations are VERY Sensitive, but when you get the page height/width right and the content size right, it does work. I had to write separate functions for paper sizes legal/letter. It's limited but works for our purposes.

I also noticed that depending on my window size it did not not always look right, but the final PRINTED product was as expected with repeating headers and footers, so I used a window that went straight to print so the user didn't notice the output, but rather saw the chrome print rendering. I hate these types of workaround but with everyone in my office using Chrome, it's a necessary evil.

3
votes

This may not be a direct answer to your question but maybe the direct solution to your problem.

After burning days and weeks on how to solve this problem, I have finally given up using direct html/css printing on repeating headers/footers. I've seen a lot of codes and samples, but everyone of them does not meet what exactly my needs, there is always missing or not marginally printing correct.

The solution to which is acceptable to mine is a combination of simple html, simple css and converting this to pdf. You'll be surprise how just simple the html structure and css is.

This solution is not entirely mine, but a combination of codes above and wkhtmltopdf library. Please don't freak-out this is very easy to install, this is what I exactly used Windows (MSVC 2013) Version 0.12.2.1, I have a windows 7 64bit with xampp as my stack. You may follow this tutorial on how to Install wkhtmltopdf

After installation you should be able to produce this code

<?php
// Test correct and failed output
// shell_exec('c:\wkhtmltopdf\bin\wkhtmltopdf --asdasdsadsad 2>> err1.txt 1>> out1.txt');
shell_exec('c:\wkhtmltopdf\bin\wkhtmltopdf --orientation Landscape C:\xampp\htdocs\test\Template.html google.pdf');
?>
<html>
    <head>
    </head>
    <body>
        <p>Magical ponies!</p>
    </body>
</html>

The content of Template.html you see in php shell_exec() is below. Let me explain quick what are these parameters are:

  • c:\wkhtmltopdf\bin\wkhtmltopdf - This is where you installed the wkhtmltopdf, location is yours to decide but for the sake of making it accessible I used C: drive just like what in the tutorial.
  • --orientation Landscape - These are one of the may optional parameters, you may refer to its official doc to know more things that you can do with the settings.
  • C:\xampp\htdocs\test\Template.html - This is the location of your html file that you want to convert, unfortunately I think you can't direct feed an html string.
  • google.pdf - Name and location of the generated file.

<!DOCTYPE html>
<html>
    <head>
    <style>
    a{
        color: black;
        text-decoration: none;
    }
    a:hover{
        cursor: inherit;
    }
    #main-report{
        width: 100%;
    }
    table { 
        color: #333;
        font-family: Helvetica, Arial, sans-serif;
        width: 640px; 
        border-collapse: collapse; 
        border-spacing: 0; 
    }
    td, th { 
        border: 1px solid transparent; /* No more visible border */
        height: 30px; 
        font-size: 11px;
    }
    th {
        background: #DFDFDF;  /* Darken header a bit */
        font-weight: bold;
    }
    td {
        background: #FAFAFA;
        text-align: center;
    }
    /* Cells in even rows (2,4,6...) are one color */ 
    tr:nth-child(even) td { background: #F1F1F1; }
    /* Cells in odd rows (1,3,5...) are another (excludes header cells)  */ 
    tr:nth-child(odd) td { background: #FEFEFE; }
    table, tr, td, th, tbody, thead, tfoot {
        page-break-inside: avoid !important;
    }
    </style>
    </head>
    
    <body>
        <table id="main-report">
            <thead>
                <tr>
                    <th colspan="9">Inventory</th>
                    <th colspan="8">Inspection Report</th>
                </tr>
                <tr>
                    <th rowspan="2">Description</th>
                    <th rowspan="2">Serial No.</th>
                    <th rowspan="2">Qty</th>
                    <th rowspan="2">Unit Cost</th>
                    <th rowspan="2">Total Cost</th>
                    <th rowspan="2">Property No.</th>
                    <th rowspan="2">Date Acquired</th>
                    <th rowspan="2">Years in Service</th>
                    <th rowspan="2">Accumulated Depreciation</th>
                    <th colspan="5">Disposition</th>
                    <th rowspan="2">Appraisal 14</th>
                    <th rowspan="2">OR No.</th>
                    <th rowspan="2">Amount</th>
                </tr>
                <tr>
                    <th>9</th>
                    <th>10</th>
                    <th>11</th>
                    <th>12</th>
                    <th>13</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000001</td>
                    <td>11/03/2000</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000002</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000003</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td>SN00001</td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000004</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000005</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000006</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td>faksdjfh skdjh h lsdjl ksd <br/> asdfjdhsfljshdfjksahdf <br/> jsdhfjsadhfjsahfkjsdhkjh</td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000007</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000008</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000009</td>
                    <td>11/03/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000010</td>
                    <td>11/04/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td></td>
                    <td></td>
                    <td>1</td>
                    <td>60,000.00</td><!-- UNIT COST -->
                    <td>60,000.00</td><!-- TOTAL COST-->
                    <td>000011</td>
                    <td>11/04/2015</td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                
            </tbody>
        </table>
    <script>
    </script>
</body></html>

here is the final result

[1]:

2
votes

The answer to this question depends on the structure of your document. If it can be structured as a series of short, unbreakable sections, then you're in luck! There is a Chrome-compatible way to simulate running page headers in this type of document (actually, it works in all of the popular desktop browsers).

The basic idea is to put a copy of the header at the top of each unbreakable section, and then use a negative margin to hide the copy so that it will only be seen if a page break bumps the section to the next page. That's a bit of an oversimplification, though, so I would recommend studying the code below before trying this on your own documents.

Test doc:

<!DOCTYPE html>
<html>
  <head>
    <style>
      .section {
        display: table;
        width: 100%;
      }
      .section > div {
        display: table-cell;
        overflow: hidden;
      }
      .section ~ .section > div:before {
        content: "";
        display: block;
        margin-bottom: -2.5em; /* inverse of header height */
      }
      .section > div > div {
        page-break-inside: avoid;
        display: inline-block;
        width: 100%;
        vertical-align: top;
      }
      .header {
        height: 2.5em; /* header must have a fixed height */
      }
      .content { /* this rule set just adds space between sections and is not required */
        margin-bottom: 1.25em;
      }
    </style>
  </head>
  <body>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
    <div class="section">
      <div>
        <div>
          <div class="header">
            PAGE HEADER
          </div>
          <div class="content">
            Unbreakable section.<br/>Unbreakable section.<br/>Unbreakable section.<br/>
            Unbreakable section.<br/>Unbreakable section.
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

You wouldn't want to use this technique in documents that have blocks of text larger than about 1/3 of a page, but it works great for docs that consist of small, discrete sections, such as forms and tables.

My answer to this other post might also be of interest. It shows how to create Chrome-compatible repeating table headers using the same basic principles, but all the extra markup is added via javascript so that it doesn't "pollute" the original HTML doc.

1
votes

I use printThis to solve the issue. You need to specify the printing area id or class name.

0
votes

Unfortunately it's a known webkit bug (Chrome and Safari) - see here. I've tried to find a workaround many times, but with no luck.

The example linked to for the accepted answer doesn't seem to work when you print from browser.