Solving the Problem with Background-Images and Print CSS

A client recently brought to my attention an issue that I always said I was going to look into more closely, but somehow just never really got around to it: print CSS.

We all know we should be doing it, but how many of us really go through our projects, page-by-page, clicking Print Preview? Well, I know I hadn’t really done much at all.

And so it is no wonder I had not come across the issue with background images before.

I think most browsers have Print Background unchecked by default, which means probably an enormous percentage of users never see our background colors or images. Getting around light-colored text that should appear in front of a background color is easy, but what about background images? You know, like graphic headers and such…

The obvious solution was to exchange the background images for good-old <img> tags, but that would mean breaking apart all those sprites I worked so hard on, and losing all the benefits of using sprites, right?

Turns out, no. Here’s what I did…

Previously, I had HTML something like this:

<h1><a href="...">This is my header</a></h1>

And CSS like this:

<style>
  h1 {
    width: 100px;
    height: 30px;
    background-image: url('mysprite.png') 10px -100px no-repeat;
  }
  h1 a{
    width: 100px;
    height: 30px;
    display: block;
    text-indent: -9999px;
  }
</style>

Right? The <h1> has the background image, positioned, and the text inside the <a> is pushed off screen, so it doesn’t interfere with the background image.

Now, I have HTML like this:

<h1><a href="..."><img src="mysprite.png" alt="This is my header" /></a></h1>

And CSS like this:

<style>
  h1 {
    width: 100px;
    height: 30px;
  }
  h1 a{
    width: 100px;
    height: 30px;
    display: block;
    overflow: hidden;
  }
  h1 img {
    margin: -100px 0 0 10px;
  }
</style>

By placing the image inline, the print CSS will see it and print it. But I can still use my sprited image as the src of the <img> tag: by using the margin, in conjunction with the overflow: hidden, I can move my image around inside the <a>, as if it were still a background-positioned image. And, I still get all the benefits of using sprites, because once the sprite is used for one <img>, it is cached and will not be fetched again for the next <img>

And of course, where I previously had inline text for accessibility and SEO reasons, but positioned off-screen for readability, I now have alt text, so no loss there either!

Just thought I’d share, happy CSSing,
Atg

2 Responses to Solving the Problem with Background-Images and Print CSS

  1. netpoetica says:

    Great, great article, you are a hero! I had never thought of using sprite maps without background image.

    I thought I would share this because I had a unique problem that was solved by this issue. I was using a webkit CSS feature called -webkit-print-color-adjust: exact; which allows background-images and color to be printed in spite of the default print behavior which is to ignore them

    After putting this app together, I ran into this immeasurably painful issue where the background-image, when printed, would scale and stretch to a huge, out of place image. I was using a sprite map – tried both PNG and SVG images. I couldn’t use backround-size because of I wanted to use only a portion of the sprite for the specific CSS class. Ultimately, I could not find a solution to this scaling issue.

    So, my CSS background image would scale uncontrollably when I would print. Using an IMG-tag based image map with margins instead allowed me to solve this printing background-image scaling and stretching issue.

    Again, thanks for the brilliant idea!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Learn More)