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 *