True printing with CSS
Section: workshop > web
Author: Steven Noble
Posted: 02/12/2002




One of the best print-friendly features of CSS (Cascading Style Sheets) is that they allow you to automatically format your Web page using one style sheet whenever visitors view it on their screen, and with another whenever they print it.

The code to do this is very simple. If you prefer the <link> tag, place the following in the <head> area of your HTML:

<link rel="stylesheet" href="name_of_screen_styles.css" type="text/css" media="screen">
<link rel="stylesheet" href="name_of_print_styles.css" type="text/css" media="print">

If you favour the @import method, try this code instead:

<style type="text/css">
<!--
@import url(name_of_screen_styles.css) screen;
@import url(name_of_print_styles.css) print;
-->
</style>

If you're an intranet developer who can direct everyone in the company to use the same Web browser, then this is all the code you need. A standards-compliant Web browser like Mozilla will automatically toggle between the screen- and print-orientated style sheets, depending on context.

But if you're a Web developer, life is not so simple. Many of the people who visit your site could be using browsers that don't automatically select the right style sheet for each media.
To accommodate the general public, Web developers must still use a server-side scripting language to build print-ready versions of each Web page. But while Web developers cannot rely on CSS alone, they should find that CSS simplifies the task of writing these server-side scripts. Here's how:

First, drop the media attribute from the <link> to your screen-orientated style sheet in the ordinary version of your Web page. Next, drop the <link> to the print-orientated style sheet altogether. Last, write the server-side script that will generate printer-ready pages for your Web site. If this script grabs the ordinary version of each Web page and feeds it into a string variable to create the printer-friendly version of the page, then it would take just one line of PHP code to modify the <link> so that it points to your print-orientated style sheet:

$output_string = str_replace ("name_of_screen_stylesheet.css", "name_of_print_stylesheet.css", $input_string);

Print style makeover

At this point, your print-orientated style sheet is just an empty file, and your printouts will be formatted as "vanilla" HTML. This is better than printing Web designs straight off the screen, as common Web effects like white-on-black text will chew through printer cartridges and be near-impossible to read when the ink starts to bleed. But let's go one better than vanilla HTML, and bring some paper-friendly pizazz to your print-orientated style sheet.

Start with the font-family property. In all likelihood, your screen-orientated style sheet specified typefaces that are designed for comfortable reading onscreen. By contrast, your print-orientated style sheet can specify any fonts you please. Just remember to provide a few alternatives, for users who don't have your favourites on their computers.

h1 {font-family: 'lucida grande', 'gill sans', arial, sans-serif;}

If you specified absolute (rather than relative) font sizes in your style sheet, then you used pixels as a unit of measurement. But there are no pixels on paper, so use points instead:

p {font-size: 12pt;}

You can't click on a hyperlink in a printout, so highlighting them with blue and underlines would simply be distracting. Make your hyperlinks look like regular paragraph text by adding this rule to your print-orientated style sheet:

a {text-decoration: none; color: black;}

The CSS spec defines an after pseudo-element and a content property that you can use to automatically print the URL in brackets after each hyperlink, like this:

a:after {content: " (" attr(href) ")"; }

However, many Web browsers do not support these abilities at present. If you're an intranet developer who can direct all employees to use a standards-compliant browser like Mozilla, this is not a problem. If you're a Web developer who really wants to emulate this effect, you'll have to write yourself a server-side script.
first-letter is another CSS pseudo-element that could come in handy when formatting Web printouts. The following code will create a "drop cap" after each major heading:

h1 + p:first-letter {
font-size: 250%;
font-weight: bold;
float: left;
padding-right: 2pt; }

The h1 + p:first-letter selector refers to the first letter of any paragraph <p> that immediately follows an <h1> headline.

The font-size: 250%; declaration increases the first letter to 250% of the size of ordinary <p> text, so it displaces but doesn't completely fill three lines. That is, there will be some room between the bottom of the drop cap and the top of the fourth line of the paragraph.

The padding-right: 2pt; declaration puts a space between the drop cap and the first three lines that sit to its right.

float: left; floats the drop cap to the left of the paragraph, so the top of the drop cap aligns with the top of the paragraph. Without it, the bottom of the first line of paragraph text would extend from the bottom of the drop cap.

Dealing with images

Automatically removing all images from a printout using CSS is as easy as everything else we've tried so far. Just add this rule to your print-orientated style sheet:

img {display: none;}

It is also possible to use CSS to insert new, print-friendly images into your printouts, but that requires a well-structured HTML document plus a Web browser that provides exceptional support for Web standards. CSS fanatics can attempt this by giving an uri value to the content property of an after or before pseudo-element (see http://www.w3.org/TR/REC-CSS2/generate.html#before-after-content). The rest of us will find it easier -- and more cross-browser compatible -- to write a server-side script that grabs the ordinary version of each page, feeds it into a string variable, and modifies the string for print. If all your <img> attributes like height and width are in your CSS style sheet rather than your HTML proper, then the PHP code that will swap your images could be this simple:

$output = str_replace ("name_of_screen_image", "name_of_print_alternative", $input);

Or, to remove every image from the string variable, you could use this line of PHP:

$output = eregi_replace("<img[^>]*>", "", $input);

In this example, PHP's eregi_replace() function will search a string ($input) for every instance of the first regular expression ("<img[^>]*>") and replace it with the second (""). The first regex will match every instance of <img , followed by any number of characters that are not >, followed by >. The second regex is empty, so eregi_replace() will delete every string that matches the first regex.

Precise page sizes

CSS allows for strict control over the size, shape and margins of the printed page. At the centre of these controls is CSS's page model, including the concept of the page box. The page model differs from the box model (which CSS uses for onscreen display) because a page has finite edge -- a printer cannot simply extend a sheet of paper whenever a GIF bleeds off the edges.

While the page has a finite height and width, there does not have to be a direct relationship between the dimensions of the page box and those of the final sheet of paper. For example, both double-sided and two-up printing involve mapping two page boxes to a single sheet. If you feel it's important to set the height, width and margins for your printouts, use the @page selector. Here is how you would use it to restrict the page box to the size of one A4 sheet of paper:

@page {size: 210mm 297mm;}
This is the equivalent rule for US Letter:
@page {size: 8.5in 11in;}

US Letter is wider (216mm) and shorter (279mm) than A4, so here's a page box that will fit on paper of either size:

@page {size: 210mm 279mm;}

Note that millimetres and inches are the measurement, as we're designing our Web site for print, not onscreen viewing. To describe your page box in more general terms, try "landscape" or "portrait" as the value of the size property.

When developing for a corporate intranet where you can control the printer, the paper size and the Web browser, you can use the @page selector to exercise more control. For example, if you require double-sided printing with wide centre margins for ring binders, add these two rules to your style sheet:

@page :left {
margin-left: 4.5cm;
margin-right: 2.5cm;}
@page :right {
margin-left: 2.5cm;
margin-right: 4.5cm;}

The inner margin will now be 4.5cm, and the outer margin 2.5cm. You can even add extravagant, 6cm margins to the first page with the first pseudo-element (which overrides the left and right pseudo-elements used above). Try this:

@page :first {margin: 6cm;}

A practical application of these abilities would be to ensure that extra-wide diagrams fit on the page, even when the document is printed in portrait mode. The first step is to assign every diagram to a class that you created for this purpose (here, we've called the class wide).

Then, give the same name (here, that's turntofit) to every page that includes an image of that class. Here's the CSS:

img.wide {page: turntofit;}

Now, simply rotate all pages called turntofit:

@page turntofit {size: landscape;}

Perfect positioning

CSS positioning allows you to disrupt the normal top-to-bottom flow of the text in a Web page.

You can use CSS positioning with a print-oriented style sheet's page model much as you would use it with a screen-oriented style sheet's box model. For example, you can modify an image's float and z-index properties to use it as a watermark on every page of a printout. But generally it's best to use CSS's paged media attributes to fine-tune printouts, instead.

Not only do these attributes retain the expected top-to-bottom flow of a printout, but they focus squarely on the one thing that matters most when printing long documents: where to put the page breaks. For example, you probably don't want your major headlines to break over two pages, or to sit at the bottom of any page of your printout. So, add the following rule to your print-orientated style sheet:

h1 {
page-break-inside: avoid;
page-break-after: avoid;}

In fact, it would be best if your major headlines did not even come near the bottom of the page. A few dangling lines of text at the bottom of a page are called "orphans". To avoid them add these rules to your print-orientated style sheet:

h1 {page-break-before: always;}
h2 + p {orphans: 2;}

This tells the Web browser to always start a new line before a <h1> headline, and to avoid printing two or fewer lines at the bottom of a page whenever a paragraph of <p> text immediately follows an <h2> headline.

Also, the page-break and orphan values tell the browser where to avoid page breaks, not where to eliminate them. This is because a print-orientated style sheet can have competing page-layout goals, which the browser must reconcile.

As well as attempting to fulfil every request in the style sheet, the browser will try to avoid page breaks within elements which have borders, and it will try to equalise the lengths of each page not ending with a forced break.

Web standards, like CSS, are designed to be "forward compatible". In other words, if you design a Web site today using CSS2, it will display correctly when the CSS3 spec is finalised and future Web browsers start to support CSS3. Conversely, when future developers start building Web sites using CSS3, their work will display adequately in today's CSS2 Web browsers. The CSS3-only flourishes will be missing when the site is viewed using today's CSS2 Web browser, but the browsers will not mangle the CSS3 layouts. To see which browsers support which print-related aspects of CSS2 today, consult CodeStyle's list: http://www.codestyle.org/css/media/print-BrowserSummary.shtml.

 



 


Hosted by www.Geocities.ws

1