Web Development

How to create CSS style sheets for printing

Learn how to use CSS to make a printed page look as good as your on-screen page. Justin James shows you what he did to make this work for one of his development projects.

I've been working on a personal project for some time called Rat Catcher. (You can read about my development work on the project in my 10-part series about the OutSystems Agile Platform.) The end goal of any usage of Rat Catcher is to produce a report, and it occurred to me that users might want to print their reports.

For a long time now, the sites I've worked on used fluid layouts that worked flawlessly with printers, but Rat Catcher is a different beast. In addition, I needed the printed reports to be better than just a page printout would normally be. It was time to learn how to use CSS to make my printed page look as good as my on-screen page. I'll show you what I did to make this work.

Ensure your HTML works well with CSS

The first thing to do is to ensure that your HTML works well with CSS. For Rat Catcher, here are the most important things I needed to do (which I had already done during the preparation for the new look and feel):

  • Wrap all of the content (including navigation, headers, footers, etc.) in a div.
  • Wrap the individual blocks in divs (header, footer, main content area).
  • Wrap a number of sub-components in divs (navigation within the header, the login information wherever it appeared, etc.).
  • Make sure that tables were only used for tabular data display.
  • All of the divs mentioned above need to have their own unique CSS class or ID.

This is all common sense, but it is really easy to forget about these details in the rush to get your application in front of people. For me, while some of it was already done up front, I did have to go back later on and update things.

Understand how the media types work in CSS

The next thing to do is to understand how the media types work in CSS. A media type defines the kinds of devices that a set of styles applies to, such as a standard screen, a mobile device, a printer, a projector, etc. If you just have a basic style sheet, your styles will apply to all media types (equal to the "all" media type). That being said, you can override the main style sheet on a per-media type basis, and also define styles specific to certain media types.

Here are the media types and their descriptions from the W3C spec:

  • all: Suitable for all devices.
  • braille: Intended for braille tactile feedback devices.
  • embossed: Intended for paged braille printers.
  • handheld: Intended for handheld devices (typically small screen, limited bandwidth).
  • print: Intended for paged material and for documents viewed on screen in print preview mode. Please consult the section on paged media for information about formatting issues that are specific to paged media.
  • projection: Intended for projected presentations, for example projectors. Please consult the section on paged media for information about formatting issues that are specific to paged media.
  • screen: Intended primarily for color computer screens.
  • speech: Intended for speech synthesizers. Note: CSS2 had a similar media type called 'aural' for this purpose. See the appendix on aural style sheets for details.
  • tty: Intended for media using a fixed-pitch character grid (such as teletypes, terminals, or portable devices with limited display capabilities). Authors should not use pixel units with the "tty" media type.
  • tv: Intended for television-type devices (low resolution, color, limited-scrollability screens, sound available).

With many of the media types, you can create an experience that is customized for disabled users who have a variety of devices to help them work.

Specify media type-specific style sheets

There are two ways to specify media type-specific style sheets. The first is to add a section in an existing style sheet using the media type separator. For example:

.class1 {

color: red;

font-size: 16px;

}

.class2 {

color: blue;

font-size: 20px;

}

@media print {

.class1 {

color: white;

}

}

All of the items in the "@media print" section override the items in the main style sheet (again, equivalent to media type "all") for any device that would be using the "print" media type. Anything configured in "@media print" that does not exist in "@media all" will not be available in "@media all" as you may expect. In a nutshell, each media type inherits from media all.

One alternative to putting media type specific information in a style sheet is to use a different style sheet for each media type. You can do this with an @import statement in a CSS style sheet by appending the media type at the end (for example, "@import url("printer.css") print"). Another alternative is to specify the "media" attribute on the link tag of the HTML that brings in the style sheet ("<link rel="stylesheet" type="text/css" media="print" href="printer.css">").

Use a device-specific style sheet

Now that we've seen how easy it is to make a device-specific style sheet, what should we do with it? While each application is a bit different, I can tell you some of the things I did with Rat Catcher.

I used display: none on many of my elements (like the navigation and login areas) to hide them; after all, those areas are useless on a printed page and just take up space. I also took the content section and, instead of having it centered with a lot of space on the side, I set it to a width of 98% with some small margins on the sides, and set it to stay on the left, as you would expect with printed text. There were a number of table styles with white-space: nowrap on the screen that I had to change to "normal" to make sure that tables with a lot of content did not run off the screen. I also made sure that the page's background was white (why waste toner/ink printing background colors?).

Summary

It took me about 15 minutes to take my existing page and morph it into something that prints well. While Rat Catcher is not suited to mobile devices, I would definitely use this technique in the future to ensure the right experience on smartphones and tablets as well.

Related reading: Try CSS media types to build printer-friendly pages.

J.Ja

Disclosure of Justin's industry affiliations: Justin James has a contract with Spiceworks to write product buying guides; he has a contract with OpenAmplify, which is owned by Hapax, to write a series of blogs, tutorials, and articles; and he has a contract with OutSystems to write articles, sample code, etc.

About

Justin James is the Lead Architect for Conigent.

11 comments
Thykingdomcome
Thykingdomcome

That was great Justin. that was realy helpful. I don't normally leave read messages in my inbox but am going to leave this one future referencing. Am currently working on a website for my school and I will need these tips for the report printing side of my project. Thanks

Beauregard T. Shagnasty
Beauregard T. Shagnasty

I've been using print style sheets for .. oh .. probably a decade or close to that. But I am not surprised that a lot of people don't know what they are. My initial prime reason for doing so was to remove non-essential items from web page printing - things like navigation that have no use on a printed page.

Mundo209
Mundo209

Nice one JJa. Did you find a way to reliably avoid splitting images over page breaks? Did you experiment with page-break-before, -inside, -after?

old graham
old graham

I must read this a bit more closely. I could never get my head around this up to now and just copy the whole lot to a pdf and link to that for a printable page. A bit of a cop out I am afraid.

Justin James
Justin James

... it was the first time that I didn't use a layout that translated nicely to print on it's own. That's one really nice thing about a fluid layout with no large images, it goes straight to the printer pretty well. In this case, I've moved to a much more fixed layout, which really requires a printer-specific style. I still see a lot of sites that print like garbage, so hopefully this reached a few of 'em. :) J.Ja

Justin James
Justin James

Using about 5 - 6 divs like I suggest doing to create a header section, a content section, etc. is quite appropriate. Note that I didn't say to use a div for every single thing... That being said, there are a couple of places in my app (particularly the menu) where I would normally consider some changes, but in my current system, it's not going to happen for technical reasons, and using div was simply a better choice. J.Ja

itadmin
itadmin

If your project is Java you can use the Flying Saucer jar to create pdf. See https://xhtmlrenderer.dev.java.net/ I've been using something based on it in Grails projects. It works well. All one needs is a print.css, media="print". In my case it sets certain areas of the page invisible and uses a serif font. It does print images and, of course, gets the page breaks right. CSS3 will have a page size attribute. See http://www.w3.org/TR/css3-page/#page-size

Justin James
Justin James

I didn't do anything with that since in my application, the only images are tiny or in parts of the page that I do "display: none" on anyways like the header. J.Ja

BlissC
BlissC

A PDF might be easier, but it's also not accessible by default, and automatically generated PDFs aren't accessible and don't meet web accessibility standards.

itadmin
itadmin

With most modern browsers one gets given a choice whether to save the file or open it. Depending on how the browser is set up, the file may be automatically opened. That's on Windows, Linux and most likely also Mac. How easy it is to get a pdf will depend on the technology one uses. With Grails, which I use, it is quite easy, provided the page to be turned into pdf is valid xhtml. Why do things the difficult way if there is an easy way to get the same results?