Making Webpages Printer Friendly

The sample from this article is available at the Gigi Labs BitBucket repository.

Introduction

I am a bit of a living paradox. Despite being a millennial and a techie, I often identify myself better with earlier generations: I like 20th century entertainment (video games, movies and music) a lot better than the more contemporary stuff, I stay away from overhyped tech I don’t need, and… I like to read text printed on good old paper a lot better than reading from a computer monitor or a tiny mobile phone screen.

Back when I launched my first website in 2002, it was common for content-based websites that wanted to be printable to provide a separate “printer-friendly version” of the page. This practice is still common today. It seemed like a lot of hassle to me at the time, though, to have to maintain two separate versions of the same content.

Fortunately, it was not long before I discoverd @media print. Indeed, the same media queries we use nowadays to allow our websites to dynamically adapt to different screen sizes (also known as responsive web design) already existed in limited form back then in CSS2. I might have used @media print as early as 2003. If nowadays we give so much importance to different output devices such as mobile phones and tablet, there is really no reason why we should disregard printers.

Showcase

Microsoft’s article on How to auto scale a cloud service is a fine example of a great printer-friendly page. Look, the page itself has lots of navigation and stuff on the side that you don’t care about when reading a printed page:

But when you go and print, poof, all thet extra stuff is gone, and you are left with a perfect, content-only page:

Not all websites have this consideration for printers. A few months ago, I opened a bug report about the Microsoft Orleans documentation not being printer-friendly. As you can see in the bug report, while the navigation was indeed being hidden, it was still taking up space, resulting in lots of wasted whitespace on the side. There was also a problem with some text overlaying the content. This was identified as a bug in DocFX, the software used to generate the Orleans documentation, and has since been fixed.

Forbes is a much worse offender. Look at how much ink and paper you have to waste on empty space, ads, videos, and stock photos, when all you want to do is read the article:

Well, at least there is some way you can read the content. Let’s now take a look at the Akka .NET documentation, for instance, the Akka.Cluster Overview:

This looks ike something I should easily be able to print and read on a plane, right? Let’s try that.

The Akka .NET team take the prize here, because the printed version of their documentation is a lot more interesting than the version you read online.

Using @media print

Making a page printer-friendly is not rocket science. Essentially, all you need is to hide stuff you don’t need (e.g. navigation) and resize your content to make full use of the available space. You can do this easily with @media print; the rules you specify inside its context will apply only to printing devices:

@media print
{
    /* Hide navigation etc */
}

Let’s take a really simple example of how to do this. This is a website layout that you can create in a few minutes. It consists of a main heading, a left navigation, and a main content section:

<!doctype html>
<html>
    <head>
        <title>My Website</title>
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
        <nav id="leftnav">
            <ul>
                <li>Home</li>
                <li>About</li>
                <li>etc...</li>
            </ul>
        </nav>
        <header>My Website</header>
        
        <section id="main">
            <header>Content!</header>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras tincidunt mollis tellus, eget maximus enim mollis lacinia. Phasellus suscipit bibendum tristique. Etiam laoreet justo ac erat tempus volutpat. Nam auctor viverra commodo. Duis magna arcu, tristique eget felis sit amet, placerat facilisis ipsum. Sed nibh dolor, congue quis ultricies sit amet, bibendum non eros. Maecenas lectus dolor, elementum interdum hendrerit vitae, placerat a justo. Sed tempus dignissim consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent tincidunt hendrerit metus, eget egestas odio volutpat scelerisque. Suspendisse sit amet bibendum eros.</p>
            <p>Nullam vestibulum blandit velit, ornare porttitor quam vehicula ac. Nam egestas orci quis orci porttitor, at lacinia risus faucibus. Vestibulum ut purus nibh. Ut ac metus magna. Nunc dictum magna non molestie luctus. Cras ornare dolor nec leo posuere, at ullamcorper lectus cursus. Curabitur pellentesque sem et nibh pellentesque pulvinar. Vestibulum non libero fermentum, luctus libero et, molestie nibh. Etiam ligula enim, mollis et ullamcorper vitae, dapibus eu tortor. Praesent pharetra volutpat orci, non lacinia leo consectetur in. Nulla consequat arcu dignissim eros ultrices, sit amet luctus ipsum ultricies.</p>
            <p>Cras non tellus leo. Cras malesuada sollicitudin mi quis tincidunt. Morbi facilisis fermentum aliquam. Donec tempor orci est, id porta massa varius a. Phasellus pharetra arcu nisl, at eleifend magna rhoncus et. Mauris fermentum diam eget accumsan dignissim. Vivamus pharetra condimentum ante, eget ultricies nisi ornare quis. Aliquam erat volutpat.</p>
            <p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse placerat nibh sit amet erat dignissim rhoncus. Suspendisse ac ornare augue. Proin metus diam, convallis a dolor eget, gravida auctor orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam at risus non neque tincidunt aliquam. Nulla convallis interdum imperdiet. Vivamus condimentum erat eget lacus tempor, id vulputate tortor condimentum. Cras ipsum velit, cursus eu sodales vitae, ornare a magna. Mauris ullamcorper gravida vestibulum. Phasellus rhoncus metus nec nulla finibus sagittis. Ut sit amet enim in purus viverra tempor vel convallis tellus.</p>
            <p>Nulla maximus urna non leo eleifend, sed efficitur libero gravida. Curabitur quis velit quam. Vivamus ac sem dui. Suspendisse quis sagittis enim. Cras feugiat nibh in lorem faucibus lobortis. Quisque sit amet nisl massa. Fusce finibus facilisis erat sed dictum. Donec ac enim ut est mattis bibendum pharetra non arcu. In hac habitasse platea dictumst. In mattis, justo non tempor convallis, ex enim luctus velit, a facilisis quam erat nec augue. Nam ac metus vel velit commodo iaculis quis a magna. Vestibulum volutpat sapien lorem, et convallis lectus lacinia non. Vestibulum fermentum varius rutrum. Etiam dignissim leo at pulvinar posuere. Sed metus nibh, commodo vitae tincidunt sit amet, pretium ut nibh. In pellentesque dui egestas, rhoncus velit nec, lobortis magna.</p>
        </section>
    </body>
</html>

We’ll throw in some CSS to put each part in its place and make the whole thing look at least semi-decent:

body
{
    margin-left: 200px;
    font-family: Arial;
    background-color: #EEE;
}

nav#leftnav
{
    position: absolute;
    margin-left: -180px;
    margin-top: 78px;
    width: 150px;
    padding-left: 10px;
    background-color: #E3E3E3;
    border-radius: 8px;
    border: 2px solid #E7E7E7;
}

nav#leftnav ul
{
    padding: 0px;
}

nav#leftnav li
{
    list-style-type: none;
}

body > header
{
    text-align: center;
    font-size: 24pt;
    font-weight: bold;
    padding-bottom: 42px;
    margin-top: 26px;
}

section#main
{
    background-color: #E3E3E3;
    margin-right: 20px;
    padding: 8px;
    border-radius: 8px;
    border: 2px solid #E7E7E7;
}

section#main > header
{
    font-size: 16pt;
    font-weight: bold;
    margin-left: 8px;
    border-bottom: dashed 2px #FFF;
}

So when you fire it up in a browser, it looks like this:

Now if we print this, we get:

Not good! Let’s fix this with a little printer-specific CSS:

@media print
{
    body
    {
        margin-left: 0px; /* remove left indentation */
    }
    
    nav#leftnav
    {
        display: none; /* hide navigation */
    }
    
    section#main
    {
        border: 0px; /* remove border */
    }
}

It looks much better now:

You can see how easy it is to make content fit neatly in a printed page without waste. In fact, in this particular example, we saved having to print a second page for content that is perfectly capable of fitting in a single page.

Not all websites need to be printer-friendly. But if your website is full of content that is meant to be read, then making them printer-friendly is probably a good idea. Given how easy it is, there is no reason why you shouldn’t make a handful of people like me happy. 🙂