How to offer good layout for printing websites without PDF: @media print

This is an article about the nice and mostly the ugly parts of customizing websites for print via CSS. During the work on our new design for Small Improvements I had to create CSS for print for the first time, following are the experiences I made, summarized in a way I think it would have helped me going this way.

Printing a Performance Review

It always seemed a strange idea for me – being born 1988 – to print out the internet. Apparently, some of our customers like to have their performance reviews in their hands so we were confronted with the odds of designing for paper with CSS. I did find a some articles about his topic, but none of them summed it up the way I needed it. So here’s my try.

First, I’ll give an overview on how to implement print styles, then give some suggestions about the workflow and at the end some general tips for styling HTML for print.

The black, white & grey theory

Some basic but very important thoughts that need to be considered realizing a print CSS. They are mostly less technical but general about the differences of screen and paper.

Printed content is static by nature – in contrast to your website which is presumably interactive in several ways. Since all the interactive parts are without use when printed, you might consider to hide them completely. But then a lot of context will be missing: a menu with the active state of the page for example, or the copyright that sits in the footer that you also hid because it’s mainly useless on paper. So sometimes adding extra headings or subheadings will be necessary.

Paper comes in two sizes in 99% of the cases: US Letter and DIN A4. With paper you got one problem less you have on screen: millions of different dimensions. I would say it’s legit to optimize just for these two paper formats.

Colors are problematic. Printers are now where screens used to be 25 years ago. For different reasons, many of the printers print black and white, sometimes just one color is empty. I would advise you to make your layout work completely without colors: no color coding or such stuff. Use high contrast: avoid grey or colored fonts. No colored backgrounds: these are often not printed.

Paper is timeless. Whenever you use relative dates: useless for obvious reasons. »Yesterday« or »A moment ago« does not help a week later. The solution is easy: just replace it with absolute dates.

Paper comes in pages. I know, there is continuous paper from the role. But usually it got pages and you don’t want your text to be cut in pieces where it would not fit. Luckily, you can prevent this so think about where there would be nice locations to cut it, above headings for example.

Preparations

The first and most basic finding is that you’ll want to start a section in your CSS and put the print stylings right over…

@media print { /* ...here. */ }

Take care that your stylesheet link does not look like this:

<link rel="stylesheet" media="screen" href="style.css"/>

The parameter media="screen" would exclude the print styles within this document.

Just drop it and everything is going to be alright:

<link rel="stylesheet" href="style.css"/>

Of course you could link a separate file for printing:

<link rel="stylesheet" media="print" href="style.css"/&gt>

But in times where minimizing the number of requests is the holy grail of page speed optimization this seems to be a thing to avoid. So you’ll be better off combining it into one stylesheet document for performance reasons.

If you worry about your CSS getting big and cluttered with the ugly print-code you probably didn’t hear of of LESS or SASS yet and should start using it right now.

Important to notice is that the the stuff inside @media print is not overwriting selectors outside of it like you might think or as I expected. An ugly way of overcoming this would be the usage of !important;. Less ugly and more easy is just to put the @media print { [...] } at the end of the document and use selectors with the same level of specificity.
If that does not work out for some reason you still can use a more specific selector than the one in the main part of your stylesheet to avoid !important;. Another way is to specify stuff that is definitely to for print within @media screen, but this is not nice either because you than exclude the myriad of other screen types.

Workflow

You don’t want to print out all the steps of the development on the printer next to your desk (although it would make a nice real-life wallpaper). The first alternative is printing PDF, which is straight forward on Mac OS.

CMD + P (CMP + option + P in Chrome) - click "open PDF in preview"

It is annoying for the hotkey-spoiled developer to use the mouse, so there’s got the be another way. Additionally it would come in quite handy to be able to use Webkit’s Web Inspector or Firebug within Firefox.

To be able to fill this needs, a nice way I found is to use

@media screen and (max-width:8.5in) { […] }

instead of:

@media print { […] }

For developing, use the code above and the browser will render close to printed version. That’s good for (un)displaying stuff on the printed version or aligning stuff differently.

Wait, there’s an even more convenient way

The method described above still comes with an annoying downside. You’ll need to switch uncomment the one line and comment out the other every time you want to see how it would look actually printed. Thankfully, there is an even better way: At the time of this writing that option just made it freshly in the newest version of Chromium’s dev-tools:

In the Web Inspectors settings, go to overrides and then select “Emulate CSS media -> print”.

This works for playing around with the layout for the most parts, but there are still things browsers do differently in print. You will need to PDF-print the website very often despite this kind of in-browser-preview.

Layout

Users printing your page are probably interested in certain parts of the website, depending on the use case you expect. Thinking about the layout, changing it to the needs of paper is the main and maybe most challenging part developing your @media print style.

Hover to see the two different versions of the performance reviews in Small Improvements.

Hiding Stuff

In most cases the only interesting part for print is the main content area, and I would assume most of the users are not interested in printing out menus or extensive header and footer graphics or sidebars. Also irrelevant might be buttons like save, back or links to share on your favorite social network because you can’t interact with them on printed paper anyway. Generally speaking, everything that is interactive on screen is not interactive on paper and thus a candidate to be hidden.

In case you used nice semantic markup and classes, this will be done fast with three lines:

.there, .is, .some, .stuff, .to, #hide {
	display: none;
 }

Please don’t uses classes marking stuff that should not be printed, that would be ugly and unsemantic.
In the other hand there should be some clue left which page was printed like a nice heading and the name of the page.

Using the whole paper

Now your content area might have a fixed with or margins to the top and such. Likely you will not want that on paper; stretching it all over might be a good idea. If you got floating images or other elements in your text, consider styling them with relative measures – % – to avoid them to be cut of or being too small, since the recalculation from px to dpi is not always foreseeable. More on that in the section Measuring.

#wrapper {
	width: 100%
	margin: 0;
	padding: 0;
}

Of course you could go crazy and design differently for paper and leave space intentionally. Take care to consider both paper formats DIN A4 and US Letter.

Measuring

On paper, there are no pixels so measuring in px might be of limited use. You can use point (pt) instead to have better control about font sizes, centimeter (cm), milimeter (mm) and inch (in) are also available. For the width of the content or full width images it might be more helpful to use percentage (%) though because the different widths of DIN A4 and US Letter can cause that your content is cut at the size on the wrong paper format.

Page Break

Pages were completely absent in my neat, scrollable world of a web developer until I started researching for the recent customer requests; sadly they need to be considered for printing. Breaking the text on wrong parts can result in really ugly results. Please do not start to dream of preventing widows and orphans, or display page numbers – as far as I know that won’t be possible. But you can control points where there will always be a page break: page-break-before and page-break-after.

Multiple interesting options are available, but just always seems to be broadly supported. You may want to use this to always start a section on a page:

section {
	page-break-before: always;
}

Or in out special case, the performance reviews should always be on separate pages, so the manager has them on separate sheets:

Hover to see the printed version

Background colors

I guess for ink-saving reasons most browsers do not print backgrounds by default. This is very important to think of, because in some cases backgrounds have certain meanings e.g. in color coded tables. Or you might have white or light text on dark background which becomes invisible without the dark background. The user can turn it on but you will be better off not trusting him in this case. If the background has an important meaning I suggest to mark it in an alternative way for printing with icons or labels. These may be hidden by default or later via:

@media screen { […] }

If you have light text on dark background it wont be readable without the dark background. Make the font black and the background white, also for ink-saving reasons.

We ran into the problem that we build a graph with DIV-boxes as dots. These were invisible on print because the DIVs were just seen by because of background. To get around this problem, I set height and width to zero and used a broad border. Borders are always printed by the browsers.

Colors

One of the first things which came to my mind doing print CSS was »Can I use CMYK?!«. Seems like you can. But I did not try really, since there will be such a huge quantity of different printers printing out our pages that such details won’t be recognized by anyone.

Cheap printers often print without colors so keep in mind that light colored fonts or those with a special meaning like color coding are not understandable without the color. In my example, the colors of the dots are found also in the heading of the associated person; without the colors the graph can not be interpreted the right way. To make that readable without color I added a description to the dot saying the name.

The problem with light color on dark background occurred at the badge showing the progress of the performance review, easily fixed by using a black color for the font:

Hover to see the printed version

Hover State

Sometimes information is hidden and just shown on hover. This helps to keep the interface clean as long as the information is not really needed. For our report, the description of the dots appears on hovering the associated person. Since you can not hover on printed pages, I made it always visible on print:

Hover to see the printed version

Text Shadow

I would question in general if it is a good idea to use shadows in your printed version. The huge differences in printers will result in an unforeseeable output. Additionally, I had very special problems using Firefox: There is a subtle text shadow which resulted in a strange blur on Firefox’ printed version:

Blurry text shadow in Firefox

Broken shadow which just appeared in Firefox

I suggest to just drop shadows for print altogether; especially text shadows.

Summary

There’s way more stuff about making a website nice printable than one would expect. But it’s quite doable and especially if you expect users to print the page I would suggest to invest some hours to get a solid result for the printed version of your website.