Getting IE7 and below to use @media print{} css
The Problem
My print css is defined in my main css file in @media print{…}. IE7 and below don’t seem to understand this.
Putting the css into another css file and using the conditional tags to add it to the head means that IE can apply the css, but how do I know when the user wants to print? And how do I know when they want to view the page normally?
The Solution
When a user clicks on my print icon (in IE7 or below) a css link element is dynamically applied to the head element, JavaScript calls window.print(), then the css link element is removed from the head element.
It almost sounds simple. It took a long time to find a working solution to this.
The Issues
1. Is the browser <= IE7?
I discovered (on StackOverflow) that a way to do this, that apparently cannot be fooled, is to use conditional comments to add an element to the DOM, and test against it.
In my <head> element
<!--[if lte IE 7]> <meta name="ie" id="ie" class="fail"/> <![endif]-->
Note: lte means <= (Less Than or Equal)
In my jQuery
if ($('meta#ie').hasClass('fail')) { // browser is <= IE7 }
2. IE7 doesn’t allow appending to the head element.
This does not work in IE7:
$('head').append('<link rel="stylesheet" src="print.css" type="text/css"');
Instead you have to use the following:
if (document.createStyleSheet) { document.createStyleSheet("print.css"); }
Note: This if statement is also a good test for any IE browser (other browsers don’t have document.createStyleSheet).
3. The page shouldn’t show with the print css after printing.
I needed to remove the print css after the print command was issued. At first I thought I may need to set a timeout for the removal, but in fact not having a timeout around the removal of the link meant that the user did not ever see the print css applied to the page. Magic!
In my jQuery
$('head link:last').remove();
4. IE does not understand display: table-cell
This was used in my print css on a table cell that was display: none in the screen css. Luckily replacing this with display: inline in the IE print css worked. In other browsers this broke the layout; they required display: table-cell.
In my print.css
td.printOnly { display:inline; }
The Final Solution
Head Element
<!--[if lte IE 7]> <meta name="ie" id="ie" class="fail"/> <![endif]-->
jQuery
$('a.ico-print').click(function () { if ($('meta#ie').hasClass('fail')) { if (document.createStyleSheet) { document.createStyleSheet("ie7print.css"); } } if (window.print) { window.print(); } if ($('meta#ie').hasClass('fail')) { $('head link:last').remove(); } });
Print.css
td.printOnly { display:inline; }