This article, while brilliant for its time, is now outdated. (Use CSS3 gradients instead.)

Recently, while trying to implement a few different navigation ideas that a designer had thrown my way, I became frustrated with my weak image editing skills. The design was gradient-heavy, so a traditional approach to navigation markup and styling would require a dozen or so background-image slices to meet the varying colors and height requirements.

Article Continues Below

After spending a mortifying amount of time creating the images—I’m a programmer by trade, so anything more complicated than MS Paint gives me the willies—I had to take a step back and figure out a better way. What if, after finishing, I needed to tweak the height? Or, God forbid, the color palette? My head was going to explode if I had to open an image editor again, so the Super Easy Blendy Backgrounds technique was born.

The blendy way#section2

Almost all the gradients in the design given to me were blended to white, so I figured that if I created a PNG that was blended from transparent to white, I could use the PNG as a background image and rely on the background-color style to provide the other half of the blend.

I fired up my trusty image editor and fumbled around until I had created two PNG images: a 100×100 px white-to-transparent blend, and a 100×100 px black-to-transparent blend. (I didn’t need the black for this application, but I wanted to see what it would look like.)

My two transparent-blend images, built in The Gimp

Using those images, I quickly threw together the CSS , and voila! Beautiful blendy backgrounds. ( IE 6 users, hang on; we’ll get it working for you, we promise.)

Here’s the CSS :

.blue { background-color: #2382a1; } .green { background-color: #4be22d; } .pink { background-color: #ff009d; } .gradwhite { background-image: url(grad_white.png); } .gradblack { background-image: url(grad_black.png); } .box { border: solid orange 2px; float: left; height: 100px; margin: 1px; width: 175px; }

Here’s the markup:

<div class="box gradwhite blue"></div> <div class="box gradwhite green"></div> <div class="box gradwhite pink"></div> <div class="box gradblack blue"></div> <div class="box gradblack green"></div> <div class="box gradblack pink"></div>

In this example and those that follow, we’re using color-based style definitions to make the example easier to understand—but we all know not to use presentation-specific words in our actual class names, right? Right.

Here’s example one, which produces this result:

A PNG gradient used as a background

After giving myself a congratulatory pat on the back, I tried to scale that div to the size that I wanted. And, as you’ve probably already figured out, the background gradient didn’t scale. Argh! I could force the background image to repeat horizontally or vertically (using repeat-x or repeat-y ), but there was no way to scale the background. (See example two if you want to feel the pain.)

CSS3 is going to implement a background-size attribute, but since CSS3 has an ETA of never, that’s no help now. So what do we do? Well, we use something that will scale, like the img element. Instead of using a background to display the PNG blend, we can use an img element, and set the width and the height to 100%.

You can check it out in example three, which produces this result:

Successful scaling—woohoo!

Here’s the new CSS (overwriting what we had before):

.blue { background-color: #2382a1; } .green { background-color: #4be22d; } .pink { background-color: #ff009d; } .gradwhite img, .gradblack img { background-color: transparent; height: 100%; left: 0px; position: absolute; top: 0px; width: 100%; } .box2 { border: solid orange 2px; float: left; height: 150px; margin: 1px; position:relative; width: 84px; }

Here’s the markup:

<div class="box2 gradwhite blue"> <img src="/grad_white.png"/> </div> <div class="box2 gradwhite green"> <img src="/grad_white.png"/> </div> <div class="box2 gradwhite pink"> <img src="/grad_white.png"/> </div> <div class="box2 gradblack blue"> <img src="/grad_black.png"/></div> <div class="box2 gradblack green"> <img src="/grad_black.png"/> </div> <div class="box2 gradblack pink"> <img src="/grad_black.png"/> </div>

The image is showing up on top of my text! What gives?#section4

Now that we have these sweet blendy backgrounds, let’s try to put some text in them. The first thing we need to do is make the boxes scale when the user resizes the text. We’ll do that by dropping the height declaration and then adding a conditional comment as a favor to IE 7, which apparently looks to the parent element for a height if none is specified. You can read more about conditional comments at Quirksmode.

Note: In real life, you’d probably want to simply include a CSS file that targets a compliant browser like Firefox and then include two more (using conditional comments that target IE 6 and IE 7). But for now, here’s that comment:

<!--[if IE 7]> <style type="text/css">.box { border: solid red 2px; height:2.5em; } </style> <![endif]-->

Text showing up behind the PNG gradient

You can follow the attempt in progress in example four. The absolutely positioned image is showing up in front of the text. To correct that, we use the universal selector to select any descendents of .gradwhite , position them relatively (greater specificity could, of course, override this as necessary), and give them a z-index of 1. Giving the img a z-index of 0 then keeps it from popping to the surface. While we’re at it, we’ll add a little style to the paragraphs to set them off.

Text correctly appearing in front of the PNG gradient

Example five does the trick. Here’re the new and updated rules:

.gradwhite img, .gradblack img { height: 100%; left: 0px; position: absolute; top: 0px; width: 100%; z-index:0; } .gradwhite * { position: relative; z-index: 1; } .gradwhite p { margin: 0px; padding: 3px; } .box3 { border: solid orange 2px; float: left; margin: 1px; padding: 5px; position:relative; width: 256px; }

And here’s the markup:

<div class="box3 gradwhite pink"> <img src="/grad_white.png"/> <p>This text is in front of the image.</p> </div>

Do you realize none of this works in IE 6?#section5

We all know that IE 6 and prior versions don’t support PNG transparencies. And since IE 7 won’t have the majority market share for awhile, you’re probably thinking that this is a great exercise in something your boss will never let you use, right? Well, IE has this great little thing called the AlphaImageLoader filter, which is explained in ALA ’s “Cross-Browser Variable Opacity with PNG: A Real Solution.” The pertinent part is that you can load a PNG image and set the filter to “scale,” thus eliminating (for IE) the need for the workarounds we used for Firefox.

So how do we make this work in both IE and Firefox at the same time? Well, we can target our styles for Firefox, and then use the star-HTML hack to override them for IE 6. I’m using the star- CSS hack here more in the interest of clarity than anything else; I think it helps to see everything together, plus it’s easier to cut and paste. When I use this technique in a production environment, I prefer to use conditional comments to target browsers. After all, hacks are hacks, and they aren’t guaranteed to work in perpetuity.

Technique working in IE6

Example six puts it all together. Here’s the CSS to add. (Line wraps marked » —Ed.)

.gradwhite { filter: progid:DXImageTransform.Microsoft. » AlphaImageLoader(src='grad_white.png', » sizingMethod='scale'); } * html .gradwhite img { display:none; }

And here’s the markup. (Don’t stare too long at the ugly inline styles—they’ll be gone in just a second.)

<div class="box gradwhite pink"> <p>Wow, maybe this will actually work! </p> </div>

Wrapping everything up#section6

Finally, we’ll add one more star- HTML rule ( position:static applied to the box class) to deal with a nasty IE6 bug that keeps links from working with AlphaImageLoader in certain circumstances.

Example seven shows our final cross-browser Super-Easy Blendy backgrounds, which look like this:

Super-easy blendys in all their glory

Here’s the final CSS in its entirety. (Line wraps marked » —Ed.)

<style type="text/css">.grad img { height: 100%; left: 0px; position: absolute; top: 0px; width: 100%; z-index: 0; } .box { border: solid orange 2px; float: left; margin: 1px; position: relative; width: 165px; padding: 5px; } .box * { margin: 0px; position: relative; z-index: 1; } * html .grad { filter: progid:DXImageTransform.Microsoft.AlphaImage » Loader (src='grad_white.png', sizingMethod='scale'); } * html .grad img { display: none; } * html .box { position:static; } .blue { background-color: #2382a1; } .green { background-color: #4be22d; } .pink { background-color: #ff009d; } </style><!--[if IE 7]> <style type="text/css"> .box { border: solid red 2px; height:2.5em; } </style> <![endif]-->

The final markup:

<div class="box grad blue"> <img src="grad_white.png" alt="blur gradient box" /> <p><a href="#">Ooo, linked text</a>!</p></div> <div class="box grad pink"> <img src="grad_white.png" alt="pink gradient box" /> <p><a href="#">Ooo, linked text! </div> <div class="box grad green"> <img src="grad_white.png" alt="green gradient box" /> <p><a href="#">Ooo, linked text</a>!</p> </div>

That’s it! In Part Two of this two-part series, I’ll explain how to work this technique into visually sophisticated layouts.