Printing from iframe when CSS is limiting

Traditional approach to printing HTML pages was to separate the stylesheets into print and screen like so:

Alternatively, you could have embedded all the styles in one stylesheet using the media queries like so:

Unfortunately, there are occasional needs to print a webpage that looks different from the main page in print.

The Solution

Instead of struggling with CSS and media queries, there is a third way; a better way: printing from an iframe.

By placing an iframe and giving it a hidden property, it will not be visible to the user, but accessible through javascript.

<iframe id="print_me" src="iframe_print_source.html" style="display: none;"></iframe>

With this in mind, we add a button that will trigger the printing of this iframe.

<button id="print_button" onclick="javascript:window.frames['print_me'].print();">Print Me</button>

This approach is made possible because each iframe is treated as a separate webpage. The iframe has its own DOM structure which you can access and manoeuvre around. The javascript that does heavy lifting is placed in the onclick handler and is triggered when the "Print Me" button is pressed.

This approach has three downsides:

  1. Two requests made to the server.
  2. Print must be triggered with javascript.
  3. Double loading of the same data.

This hack works and can be extended to fix the problems listed above in several ways.

The first downside can be resolved by creating the iframe dynamically and loading the content to print only when the print button is pressed. This fix becomes a strong positive when printing involves heavy styling. You don't want to waste any bandwidth on print styling -- assuming the user does not print that often.

The second point can be partially resolved by adding a listener on the keyboard and trigger the print action when 'Cmd + P' or 'Ctrl + P' is pressed on the keyboard.

The third point is actually an advantage that we are utilising in this case by changing the content. This means that you can place a completely different stylesheet (or even a different content) within the iframe without breaking the parent page.

Also, here is why you should avoid media queries:
Peter Griffin demonstrates CSS