Saturday, January 14, 2012

Printing Main Content Only

The Issue

I was recently asked if it was possible to only print the main content of a page. Occasionally users will print an APEX page by choosing File >> Print in their browser, and the resulting printed output can be a bit messy or contain information they do not care to see. In many cases this is a report the user has filtered and wants to bring to a meeting. Necessary layout components, like a header or sidebar, consume page real estate without providing important information to the printed document. This wasted space can push the content so that the report the user wants to see now prints on multiple sheets of paper.



So the question is, can we print only the main content of a page?


The Solution

Printing the main content of a page can be achieved by using CSS Media Types to style the page differently when it is rendered for a browser than when it is rendered for printing. The solution I opted for was to hide every element on the page except for the element with id="print-content". The idea was originally posted on stack overflow, but I have also included a few helper classes for "print-only" and "no-print" content from within the print-content element. In other words, you may have two regions in the print-content element but you only want one of them to print; the one you do not want to print would be given class="no-print".

Modify the Page Template

Include the following style within the head section of your template. Notice the use of @media print. The enclosed styles will only be applied when the page is being printed.

<style type="text/css"> .print-only{ display: none; } @media print { body * { visibility:hidden; } #print-content, #print-content * { visibility:visible; } #print-content { position:absolute; left:0; top:0; } .print-only { display: block; } .no-print { display:none; } } </style>
Specify Print Content

In this example I am using theme 21 - Scarlet and I am using the One Level Tabs - Left Sidebar (fixed-width / DIV based) page template. I only wanted to print the BOX_BODY and REGION_POSITION_03, so I wrapped that part of my template with a print-content div.

<div id="header"> <div id="logo"> <a href="#HOME_LINK#">#LOGO##REGION_POSITION_06#</a> </div> #REGION_POSITION_07# <div id="navbar"> <div class="app-user">#WELCOME_USER#</div> #NAVIGATION_BAR# #REGION_POSITION_08# </div> </div> <ul id="tabs"> #TAB_CELLS# <li class="last"><span></span></li> </ul> <div id="topbar">#REGION_POSITION_01##REGION_POSITION_04#</div> <div id="messages"> #SUCCESS_MESSAGE##NOTIFICATION_MESSAGE##GLOBAL_NOTIFICATION# </div> <div id="body"> <div id="two-col-sb-left"> <div id="left-sidebar">#REGION_POSITION_02#</div> <div id="main-sb-left"> <div id="print-content"> #BOX_BODY##REGION_POSITION_03# </div> </div> </div> </div>
Have a look at my demo app and try printing the page. The header and sidebar of the page will not show up in the printed document.