Post Archive

› November 28, 2005

Single Image Multi Replacement

  • Reported by Alessandro

In recent times, attention over image replacement techniques has decreased significantly thanks to the flexibility and easiness of solutions like sIFR.

But sometimes for design reasons, image replacement techniques still remain a good option. Between the many, the ones I've always liked most are the solutions by Gilder and Levin, which use extra markup (an empty span that doesn't affect content) but keep the CSS easy and simple without the need of hacking and, most of all, maintain accessibility intact in the case of images turned off scenario.

While looking for a simple solution to keep both CSS and images as light as possible, I came up with the SIMR (that stands for Single Image Multi Replacement), which uses a single image to replace more than one heading. Nothing execptionally new, since combining images in one for rollovers or to get a whole menu with an single image are already known options. But I thought it was worth sharing, since combining all graphics for headings in an image could be new to some of you. SIMR is not to be intended as a new image replacement technique, but rather, as a design methodology with a different approach.

So here it's the example I prepared, in which every h2 in the page is graphically replaced, with a single image used. Let's see an extract from the markup:

<div id="content">
<h2 id="what"><span></span>What? A single image?</h2>
<h2 id="benefit"><span></span>Bandwidth benefits</h2>
</div>

As you can see, each h2 element inside the content div has an id, and an empty span before the text. Now let's see the CSS. First, the rule on h2 elements. We'll set them relatively positioned in order to allow absolute positioning inside. The dimensions will be equal to a single portion of the image that will be used for headings. Margin will be adjusted and font will be styled in case images are off. A different color from the body text, a small font, and small-caps, will suffice:

div#content h2{position: relative;width: 350px;height: 40px;
    margin: 2em 0 0;color: #847FB7;
    font: bold small-caps 90% Arial,sans-serif}

Now the span elements, that will be absolutely positioned with the same dimension of headings and with the background-image that combine all headings:

div#content h2 span{position: absolute;
    width: 100%; height: 100%;
    background-image: url(simr.jpg)}

Finally, for each heading we'll specify the background position:

h2#what span{background-position: 0 0}
h2#benefit span{background-position: 0 -40px}
h2#intact span{background-position: 0 -80px}
h2#easier span{background-position: 0 -120px}
h2#updates span{background-position: 0 -160px}

That's it, you can see again the example. Compatibility should be extend to every browser with a minimum of CSS support, the technique has been tested in IE5.x, IE6, Opera, Firefox and Safari. You may want to look how the page would render with images turned off. A few words on pros and cons of the technique.

Pros are that replaced content is accessible to screen readers, text browsers and with images turned off. Besides, a single image surely weighs less than, say, five images, and requires a single transfer instead of five. CSS is lighter and quite easy, and I think that the technique could bring significant time sparing in the development process.

A con is loading time: the waiting time for the first graphical heading to show is surely more than an image replacement method that uses a single image for each heading. Also, it's not easily maintanable for updates. For that reason, it's suggested for sites where updates are low, or the need of additional graphical headings will be rare.

Finally, several strategies on SIMR usage could be considered. You can replace for example all main headings accross different pages, or use a single image per page when more than one heading is planned. As a general rule, a single image shouldn't weight more than 20-30Kb for obvious reasons, and you can arrange an image per page. In these cases, you could add an id to the body element and get another level of customization using descendant selector. For instance:

div#content h2 span{position: absolute;
    width: 350px;height: 40px}
body#home div#content h2 span{
    background: url(home.jpg)}
body#portfolio div#content h2 span{
    background: url(folio.jpg)}

Rules about the spans and headings will remain similar to those of the previous example. Obviously, more complex solution of the approach should be evaluated case by case, but I hope the methodology is clear. Enjoy!

Comments

1. November 28, 2005 10:39 AM

Quote this comment

Pup Posted…

Nice writeup

I used this concept in the development of the new Shacknews.com about a year ago. Using a single sprite instead of multiple small images took image hits for the homepage from several dozen down to 2, reducing total http hits by 75%, and cutting bandwidth requirements in half (the semantic html and css also helped here, too). Another added benefit is that the page renders extremely fast, since it only has to load up 2 images (this one and this one).

This technique was also used on Filecloud (main image), Gamecloud (main image), and a few others I've worked on.

2. November 28, 2005 02:11 PM

Quote this comment

deelan Posted…

Nice one, Alessandro. I've recently done some experiments with background-position too and came up with Ghost Thumbnails -- which is essentialy a way to store the thumbnails of the photo gallery in a single file and then move it around to accomodate the preview for each thumbnail.

Since I'm lazy I've automated the creation of the single image via a Python script. Later i've discovered the ALA article CSS sprites which do essentially the same thing, in another context.

It was funny, though.

3. November 28, 2005 02:55 PM

Quote this comment

Matthew Pennell Posted…

Genius, I can't believe that it's never occurred to me before!

4. November 28, 2005 03:50 PM

Quote this comment

matt Posted…

Very useful, I remember looking at my speed report and thinking, how can I reduce the http requests? this does exactly that.

It's some that could be adapted quite easily too, after the initial mockup of a design I tend to separate the main elements e.g. header, menu, etc.. So instead of cropping them I could use something like this. Then use one image for the header, one for the menu, etc.. which would cut down on loading issues.

5. November 28, 2005 06:29 PM

Quote this comment

Dustin Diaz Posted…

I believe this was already coined as the CSS Navigation Matrix

6. November 28, 2005 06:49 PM

Quote this comment

Nate Posted…

Dustin - Alessandro links to that (an updated version) in his article.

7. November 28, 2005 08:36 PM

Quote this comment

Dustin Diaz Posted…

That's my bad. I did a quick skim through each link and suppose I missed that one.

8. November 29, 2005 10:45 AM

Quote this comment

Aadesh Posted…

As dustin said, its similar to CSS Navigation Matrix. Donno what to say, a disadvantage or something else, but here, u'll first have to find out how many headings will appear on a single page and accordingly create an image with all the headers in it and then, each time when you want to use a different heading, u'll have to play aound with their Y-Position. nevertheless, a neat effort!

9. November 30, 2005 09:52 AM

Quote this comment

Petros Posted…

I am truly amazed with the techique and the posibilities. With changing just the saturation (let say) of the image you skin the website in a second.

I think it worths of a tutorial of the http://www.filecloud.com/ website.

10. November 30, 2005 05:51 PM

Quote this comment

Justin Reid Posted…

I agree with Aadesh. You'd have to know what each heading is prior to creation. And if you wanted to change a heading it might be simple, OR it might be a huge pain if that heading runs longer than it's current line.

Lets say the first heading is one line, something like "How To Fix a Website", and the client wants it changed to "How to Fix a Website in 10 Easy Steps or Less", and it now goes into two lines. You'll have to reslice the image, and if it's the first title on the page then you'll have to update the y-coordinate for each of the trailing headers.

So I would use seperate images, but very similar CSS. In fact, you can write the background properties like so:

div#content h2 span { background-position: left top; background-repeat: none; }

And then list out the backgrounds like so:

h2#what span{background-image(../img/title_what.gif);} h2#benefit span{background-image(../img/title_benefit.gif);} h2#intact span{background-image(../img/title_intact.gif);} h2#easier span{background-image(../img/title_easier.gif);} h2#updates span{background-image(../img/title_updates.gif);}

Still clean, minimal image bandwidth (if sliced properly) and removes interdepandency on these IDed elements.

11. December 1, 2005 01:33 PM

Quote this comment

Rob Goodlatte Posted…

Nice post, but this type of image replacement is fairly obvious - I don't think it merits a new acronym. Use of background-position for image replacement entered mainstream use with Shea's CSS Sprites article.

The last thing the web needs now is more coined terms

12. December 1, 2005 02:38 PM

Quote this comment

Alessandro Fulciniti Posted…

Rob, as I said it's nothing really new, and it's not intended as a new groundbreaking technique, but instead a possible aproach. Combining images in something that comes togheter (i.e. a navigation) is fairly obvious, could be less dealing with headings. Besides, my objectives in writing are to pass something useful to someone, not to present at all costs something new. And, reading some others comments, I guess I've managed quite well.

13. December 2, 2005 04:13 AM

Quote this comment

Rob Goodlatte Posted…

My apologies if I came across as rude. I think it's great to spread knowledge of these techniques, my only quibble was with your acronym. There's just far too many of them out there these days :)

14. December 2, 2005 04:25 AM

Quote this comment

Alessandro Fulciniti Posted…

Rob, no problem :-)

15. December 2, 2005 05:38 AM

Quote this comment

henry Posted…

hey!

what an awesome idea! even when it's not really nu

i love this css-game!

greetings from germany

henry

16. December 7, 2005 01:39 PM

Quote this comment

Mauricio Silva Posted…

Hi Alessandro

I'd like to translate to Brazilian Portuguese this valuable article. So, I'm requesting your/site's owner permission for the translation. Looking for reply with best regards.

17. December 9, 2005 01:33 AM

Quote this comment

Alessandro Fulciniti Posted…

Mauricio, no problem if you provide the link to the original article.

18. December 11, 2005 03:54 AM

Quote this comment

Ruud Bruijnesteijn Posted…

To be used with care!! You might run into the 'IE Empty Span Fly By' bug when you have just an empty span inside a block element.

To see it in action, add a background-color to #content, add a non zero padding-bottom to #benefit and drop the text "Bandwidth benefits". Now everything above the empty span, including any pictures that you try to embed in the #what element, will be affected by the bug and might/will become (partially) invisible. This is a dynamic issue, it happens on initial load and while scrolling using the vertical slider. The faster you scroll, the more text and graphics will be obscured in IE!

Here's an example that will reveal the bug:

h1 { background-color: #ffc; }
h2 { padding-bottom: 1px; }
.Outer { background-color: #fcc; }

<div class='Outer'>
<h1>Visible</h1>
<h2><span>Lorem Ipsum</span></h2>
<p>Lorem ipsum dolor sit amet, adipiscing elit</p>
</div>
<div class='Outer'>
<h1>Invisible in IE6 due to the Empty Span FlyBy bug</h1>
<h2><span></span></h2>
<p>Lorem ipsum dolor sit amet</p>
</div>

Feel free to add more lorem ipsum, or copy in more "outer" divs such that the page runs off the bottom of your screen. You'll see some weird things in IE!

19. January 11, 2006 04:39 AM

Quote this comment

Mauricio Samy Silva Posted…

Brazilian Portuguese translation for this article is alive at: http://www.maujor.com/tutorial/simreplacement.php

20. January 12, 2006 04:42 AM

Quote this comment

Posted…

FireFox with Validation Standart plugin return me : line 30 column 15 - Warning: trimming empty and for more line