Take full control of what elements from a web page you want to print without the annoying pop-up window called “Print-friendly Version”. How? With a hidden iFrame, a CSS stylesheet for print and a little bit of JavaScript.

Printing a web page often results in a document that is not optimal for reading. That’s why the CSS stylesheet for print was invented – simply add media=’print’ when loading the stylesheet. This is a technique most web designers already know, using it to disable unwanted elements like headers, menues and Flash animations on the printed document.

For a normal web site this will often be sufficient, but when you have a advanced web application, things get a lot more complicated. There will be a lot more elements, these might get loaded with AJAX and a lot of absolute positioning is used.

That is the reason why we often see the “Print-friendly version” button, that will extract a specific portion of the current page, open a new window, paste the content into the new window and invoke the print dialog. Countless examples of how to do this can be found on Google.

I have been using this technique and I think it is working well, but the first thing the client usually says, is: “Why is this little window coming up there?” And of course the client is always right, right? So I went looking for a better solution…

The trick is to use an iFrame instead of a new browser window. So you place an empty, invisible iFrame somewhere in your HTML and at print time you paste your content in there and print it. Simple and beautiful.

Example:

<head>
<script type="text/javascript">
function ClickHereToPrint() {
	try {
	var ifrm = document.getElementById('ifrmPr');
	var content = document.getElementById('divToPrint').innerHTML;

	/* Determine what DOM model to use */
	var printDoc = (ifrm.contentWindow || ifrm.contentDocument);
	if (printDoc.document) {
		printDoc = printDoc.document;
	}

	/* Create a HTML document to go into the iFrame */
	/* The title will appear on the printed document */
	printDoc.write("<html><head><title>title</title>");
	printDoc.write("</head><body onload='this.focus(); this.print();'>");
	printDoc.write(content + "</body></html>");
	printDoc.close();
	}

	<!-- If, for some reason, the above fails the
	whole document will be printed the normal way -->
	catch(e) {
		self.print();
	}
}
</script>
</head>
<body>
<!-- The following will NOT be printed -->
<p><a href="#" onclick="ClickHereToPrint();">Print</a></p>
<p>Nulla facilisi. In vel sem. Morbi id urna in diam dignissim feugiat.</p>

<!-- The following will be printed -->
<div id="divToPrint">
	Here goes the content to be printed.
</div>

<!-- The empty, invisible iFrame -->
<iframe id='ifrmPr' src='#'
	style="width:0px; height:0px; border: none; background:transparent">
</iframe>
</body>

Taking it further

The example above will use the default CSS in the printed document. Creating a custom CSS stylesheet for the print is a natural step. Create a CSS stylesheet and add some rules of your choosing.

Here’s some inspiration:

* {
	margin			: 0;
	padding			: 0;
}

body {
	margin-left		: 30px;
}

h1, h2, h3 {
	font-family		: 'Helvetica', Arial, sans-serif;
}

Assuming you saved the CSS stylesheet with the name “print.css”, we can now use when printing.

After

printDoc.write("<html><head><title>title</title>");

add the following to the HTML document:

printDoc.write("<link rel='stylesheet' type='text/css' href='print.css' media='print' />");

Taking it even further

You have full control over the content and using the printDoc.write command you can add any content you want, e.g. a front page or special styling for IE using conditional comments.

You can also manipulate the DOM elements of the content before printing it. As an example I have a web application, which is relying heavily on the AJAX framework Dojo. Having a lot of elements, which can be open and closed, it’s nice to print only the open elements. But when printing the open button of the closed elements will still appear on the print.

Here’s a code example using Dojo on how to do this.
It would replace:

var content = document.getElementById('divToPrint').innerHTML;

Of course you would also need to import the Dojo library to make this work, so it is only meant as an inspiration:

var content = dojo.clone(dojo.query("#divToPrint")[0]);

dojo.query(".openCloseElementContent", content).forEach(function(inputElement){
	if (inputElement.style.display=="none") {
		inputElement.parentNode.style.display="none";
	}
});

content = content.innerHTML;

What happens when the user chooses Print from the File menu?

One issue with this technique is to educate the user not to print the conventional way, either by selecting the Print command from the File menu or by pressing Control-P / Command-P.

This can not be avoided, but we can make it clear to the user, that this is not the prefered way to print, but adding a div to the beginning of the document, that say “Please only print using the dedicated print icons!” This div is hidden on screen, but not on print.

Posted Saturday, April 25th, 2009 at 4:14 pm
Filed Under Category: Ajax, CSS
You can leave a response, or trackback from your own site.

5

Responses to “Print a specific DIV using an iFrame, CSS and JavaScript”

Dave

This is great and exactly what I was looking for, thanks for sharing!

Siva

Excellent tutorial. Thanku very much, i was looking for the same problem since many days for my project which i should deliver to client.

Thanku

Mohamed Rafiq

Excellent tutorial :) Thank you very much!

Yash

Thanks much. I was looking same solution.

Nouman

Great Work . I am freelancer and I was struggling with pdf document printing . I use your code and show another Iframe in divToPrint and when I pass the print command I just say hurrrraaa.. I have done with your example.

Leave a Reply