Despite a cascade of writing across the web about user centered design, little attention is devoted to setting up web pages for print. Possibly this is because most web professionals rarely print web pages. I can’t remember the last time I printed one. But many people do regularly print pages from websites. And if we want to support all of our users, we need to support users who print web pages.

A post by Manuel Matuzovic at recently got me thinking about CSS and print media. Click here to view Manuel’s article at

What follows is a simplified yet expanded and reduced version of Manuel’s suggestions. Yes, all three 😀  The instructions are generally applicable to CSS that’s intended for print. For more specific information about how to add an @page media query to a WordPress installation, see the Codex. The instructions on this page will still apply once you know where to put the code.

Always test your CSS in every browser you want it to work in. Not all code works in all browsers — and sometimes the same code works differently in different browsers.


1. Embedding Print Styles

You’ll usually want to embed your print styles in your stylesheet (see below for an alternative approach). You will already have styles set for the screen, as in this hypothetical style:

// CSS for Screens
body {
    font-size: 18px;

To create a print style, you will need to create a media query for print. Once this is crated, all of your print styles will be placed here.

// Media query for print
@media print {
    /* print styles go here */
    body {
        font-size: 28px;

Alternatively, you could use HTML on the page. In general it’s messier and adds another request from the browser to the server, so its usually not a good idea. But there are situations that call for it. Here’s the code:

<link media="print" href="print.css" />


2. Testing

Manuel helpfully points out a few testing methods that don’t require actually printing pages. See his article if you want more ways to go about it. The simplest way, though, is to print to PDF or look at a print preview, depending on your browser and environment. If you want to debug print styles in your browser, look at Manuel’s original post. He tells how to debug in Firefox and Chrome.

3. Absolute Length Units

Unless you’re coding for a specific device, it’s generally good practice to avoid absolute length units for on-screen display. But absolute units are the first choice for print.  Here’s a handy reference chart from the W3C (World Wide Web Consortium):

The absolute length units are fixed in relation to each other and anchored to some physical measurement. They are mainly useful when the output environment is known. The absolute units consist of the physical units (in, cm, mm, pt, pc, q) and the visual angle unit (px):

unit name equivalence
cm centimeters 1cm = 96px/2.54
mm millimeters 1mm = 1/10th of 1cm
Q quarter-millimeters 1q = 1/40th of 1cm
in inches 1in = 2.54cm = 96px
pc picas 1pc = 1/6th of 1in
pt points 1pt = 1/72th of 1in
px pixels 1px = 1/96th of 1in

Here are a few examples of possible stylesheet usage. Use whichever measurement is most suited to you and the device for which you’re writing.

h1 { margin: 0.5in }      /* inches  */
h2 { line-height: 3cm }   /* centimeters */
h3 { word-spacing: 4mm }  /* millimeters */
h3 { letter-spacing: 1Q } /* quarter-millimeters */
h4 { font-size: 12pt }    /* points */
h4 { font-size: 1pc }     /* picas */
p  { font-size: 12px }    /* px */

All of the absolute length units are compatible, and px is their canonical unit.


4. Page Specific Rules: @page

If you are a print professional, many things you already know transfer well to current CSS and web browsers. It just requires a slightly different language. What follows here is a brief introduction to @page rules. MDN (Mozilla Development Network) has a relatively complete reference for @page. CSS is continuously in development, but the most full description of the paged module can be found at the W3C. The website A List Apart has a comprehensive tutorial about how to build books with CSS.

Briefly, the CSS for @page is itself a media query and looks like this:

@media print {
     @page {
        margin: 1cm;

A. Page Breaks

A web page can be nearly endlessly long. Pieces of paper have defined lengths. There are five CSS properties that can be used to control where a page breaks.

i. Before an HTML element

To break the page before every HTML5 semantic <section> element

section {
    page-break-before: always;

page-break-before applies only to block elements that generate a box. It is gradually being replaced by “break-before”. See page-break-before for a full description and options.

ii. After an HTML element:

page-break-after let’s us force or avoid page breaks after an element.

h2 {
    page-break-after: always;

page-break-after is gradually being replaced by the more generic break-after. break-after also handles column and region breaks and is syntactically compatible with page-break-after. See page-break-after for a full description and options.

iii. Avoid a break inside an HTML element

ul {
    page-break-inside: avoid;

See page-break-inside for all options.

iv. Widows

As you probably know,a widow is the last line of a paragraph appearing alone at the top of a new page. Even if you don’t want to force a page break at a certain point, you might want to control the number of lines that are forced to the new page. In CSS, the default value is two lines, i.e., if only one line doesn’t fit on the page, two lines will move to the next page, but it must be explicitly applied. You can easily change the value. If you want a minimum of four lines to move to the next page, use this:

p {
    widows: 4;

MDN has a more complete description

v. Orphans

While “widows” refers to the top of the next page, “orphans” refers to the bottom of the previous page. The CSS orphans value specifies the minimum number of lines in a paragraph that must be left at the bottom of the previous page when a paragraph is split between pages. The initial value is two. A value is applied like this: 

p {
    orphans: 3;

MDN has a more complete description

5. Reset Styles

It will often make sense to reset some styles, such as background-color, box-shadow or color for print. This is accomplished with something like this:

li:first-line {
    background: transparent !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;

A print style sheet is one of the few exceptions where the use of !important 😉 is not controversial.

6. Exclude Unwanted Content

To avoid wasting ink, you can remove presentational content, ads, navigation, etc. with display: none. Use display: none on any element you want removed from the final printing.

You might even want to just show the main content and hide everything else, like this: 

body > *:not(main) {
    display: none;

See a full description of the display property on MDN.

7. URLs in Links

Since web pages generally hide actual links behind text, you need a way to display the links when you print a web page.

It’s straightforward to reveal a link’s target next to the text displayed on the web page:

a[href]:after {
    content: " (" attr(href) ")";

This will display relative (partial) links, absolute links to your website, anchors, and so forth. Something like this might serve better:

a[href^="http"]:not([href*=""]):after {
    content: " (" attr(href) ")";

This probably looks a bit complicated. But if you just replace “” with your domain name (i.e. no “http” or “www”), this will ignore internal links and only display links to external sites.

8. Revealing Abbreviation Expansions

Best practice on a website is to wrap abbreviations in an “<abbr>” element. When this is done, the expansion of the abbreviation is placed in the “title” attribute. Or, as MDN puts it:

The HTML <abbr> element (or HTML Abbreviation Element) represents an abbreviation and optionally provides a full description for it. If present, the title attribute must contain this full description and nothing else.

<p>I do <abbr title="Hypertext Markup Language">HTML</abbr></p>

See more in depth examples in the How to mark abbreviations and make them understandable article.

If you wish to expand the abbreviations on a printed page, you can use something like this:

abbr[title]:after {
    content: " (" attr(title) ")";

9. Free Frameworks

A framework can do most of the work for you. If you’d like to control printing but not have to do all of the detailed coding, one of these frameworks could work for you. Both of them are essentially in-depth printing stylesheets. Both of them are free. And both of them are hosted on GitHub, one of the main hubs of the OpenSource community.

A. Gutenberg

The Gutenberg framework makes optimizing for print a little easier.

B. Hartija

Hartija. is another framework for print style sheets. This one is by Vladimir Carrer.


If you enjoyed this post or have comments, I’d like to hear from you. If you didn’t like it, I’d like to hear from you too, and I hope you’ll tell me why.

Pin It on Pinterest