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.
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. (IE6 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
Hey, it’s not scaling!#section3
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 IE7, 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 IE6 and IE7). 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 IE6?#section5
We all know that IE6 and prior versions don’t support PNG transparencies. And since IE7 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 IE6. 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.
Interesting.. This could be pretty useful when making mockup designs. But I’d prefer the “real thing” when doing something for production use; That IE PNG hack looks pretty ugly when you select it in the browser so I usually prefer not using it when I’m able to.
And I don’t think this is something big enough to justify breaking of breaking the semantic markup rule. But that might be just me.
But this brings the idea of creating a script (PHP or something) that takes first and second color, size and alignment and generates the picture for you.
And I can’t see why you have 100px width on your images when one is enough. It doesn’t add many bytes, but still some..
Now I should stop complaining. I had a great time reading the article.
We’ve been using this technique for a while and one thing that helps is to create a set of incrementally more transparent versions (we used increments of 5% so there are 20 of each). Also it can be useful to have left-right and right-left versions too.
I think it’s worth pointing out that the images should be 256×256 for completely smooth gradient.
Nice article. Would it be possible to refine this technique by inserting the extra image tags using javascript? It would certainly make the markup cleaner.
I didn’t know the technique to use PNG for IE6 as background-image, really useful.
The possibility to have PNG background working with text resizeable it’s really a technique without price. I guess that it’s really useful for make navigation buttons.
I guess that it’s possible either use different colours of gradient instead than black and white, so could be a good mixture of effects.
I really liked this article! Thank you for the hard job.
The backgrounds are broken in Opera 9 on Windows XP. They show a gap at the right.
That’s not only Super-Easy, it’s Super-Cool!
The downside is that I’m now going to ‘waste’ half my potentially productive morning playing with gradients 😉 Brilliant.
Hmm, can’t get the gradients to show in IE6 either. Maybe it doesn’t work with the standalone version. (I can’t log on for comments using that either!) Works fine in IE7.
bq. The backgrounds are broken in Opera 9 on Windows XP. They show a gap at the right.
This seems to be pretty easily fixed. The problem is just that Opera measures the 100% width of the image without the 5px padding of the box class and so results in a 10px gap.
By removing the padding from the box class and putting it on the
tag within the box class the 10px gap on the right hand side is fixed.
It might be an idea to think about using a inside the box to provide this padding.
I like this article, because it gives some new ideas for trying new things. At th moment, I prefer gradients within the same color, for example light blue to dark blue, but this is only my taste.
bq. Would it be possible to refine this technique by inserting the extra image tags using javascript? It would certainly make the markup cleaner.
Spartan markup is inherently beautiful – but who is it for? The designer or the end user?
Gradients have resurged. There was a period when solid rectangles of low-hue colours were the only truly safe thing. I’m very interested in the causal relationship between things like gradients and rounded corners falling back into fashion, and the innovative techniques for them (such as this) making waves.
Nice article. Very good run through of cross-browser application and an excellent manner of backing up convenient, legible, practical examples with, ‘and of course, there are standards and conditional comments’. Hehehe.
bq. Spartan markup is inherently beautiful — but who is it for? The designer or the end user?
Spartan markup is good for those who will maintain site later.
It is good not to have fish out parts of the design from markup, when the rest is in CSS.
And if you feel that you must have decorative images in your markup—at least make sure they have alt=””.
Hi,
Although this technique is a vigorous CSS workout, and very appreciated, it seems like a great amount of additional markup. This at first glance defeats semantic usage of XHTML/CSS.
I’ve been using this technique for the last year or so, but recently stopped because of issues involving Links being “unclickable” within these DIV tags in IE 6. Also CSS won’t validate with this hack.
Guess we can just hope that with MS pushing IE 7 in their monthly updates we’ll have a quick jump to 7.
I do think it would be better to utilize a DOM-inserted image with this instead of all the unsemantic code; it could be easily done with something like jQuery – that way you just add a gradient class onto whatever you want to have the gradient as a background image. This keeps your xhtml semantic for browsers that don’t support javascript (such as lynx, some screenreaders, etc) while giving the users that do support it nice eyecandy.
To make it degrade nicely in browsers that do not support javascript, just have a nice median background color.
I realize that not everyone cares about such things, but AlphaImageLoader isn’t valid CSS. Perhaps this should be noted in the article?
Honestly, what i was more impressed by is Kevin’s beautiful illustration. Very well done!
That’s intresting!
But is possible to do it without pictures isn’t it?
I don’t now if you need to use JavaScript too but that could be i ntresting, I hope that you’ll write something about this argument.
Quite a good read, thanks for the article.
The system we use is content managed, so quite often the clients will add their own copy, and often want to include images.
The way that you’ve setup the CSS for this, any images within the containing box div; even if you have div’s within this or within other container tags (p, blockquote and stuff); will be affected by the styling.
Would it perhaps be better to set a class on the gradient image of “gradietnImg” (or something) and then apply the “.grad img” to that, so that it becomes something like this; “.grad img.gradientImg”?
Just a thought.
» Sturm
First time posting on ALA, and it goes and strips out all my pretty quote tags 🙁 oh well, forgive this, but i’ll repost the comment with normal tags:
Quite a good read, thanks for the article.
The system we use is content managed, so quite often the clients will add their own copy, and often want to include images.
The way that you’ve setup the CSS for this, any images within the containing box div; even if you have div’s within this or within other container tags (p, blockquote and stuff); will be affected by the styling.
Would it perhaps be better to set a class on the gradient image of “gradietnImg” (or something) and then apply the “.grad img” to that, so that it becomes something like this; “.grad img.gradientImg”?
Just a thought.
– Sturm
When I was messing with this a little bit ago I found this trick quite useful:
When you don’t want the gradient to be a perfect gradient and you just want it to look pretty near the bottom or top of the element or something, you can use background-position to lower the gradeint (or raise it) depending on if it’s meant for the top or bottom of the element.
If you have a gradient that’s solid at the top, you can use something along the lines of this to bring the gradient up into the element so it appears to start sooner.
background: red url(“shadow.png”) repeat-x 0 -10px;
Hope someone finds this useful!
I typically use a JPEG background image with a smooth gradient about half the height of the parent anchor block and only a couple pixels wide. I stick this background to the bottom (or top) of the blocked link and repeat it on the X axis. The disadvantage is the max-height of the gradient is defined by the image height so that when the text is enlarged greatly I end up with more background color than gradient portion, but being that it’s valid, and it uses less mark-up and CSS — I only style and block the anchor itself, not a container — and the image size is next to nothing, I guess I can live with that. I must say, though, this technique is intriguing and I may use it, in part anyway, down the road when IE6 is just a bad memory.
sorry to be slightly offtopic but the example html markup uses 3 class names attached to a div…is there a limit to the class names which can be applied to a single element? googling only brought up an unanswered comment on meyerweb and i stopped testing when 9 classes worked perfectly!
till the second part comes along, i’ll use this to impress my collegues 🙂
As a beginner in webdesign, I think it’s very interesting.
Good job, Matthew!
Pretty good tutorial, please more of that.
Gradients are evil and should only be used under adult supervision.
You might want to check my 3 demos for non-image CSS gradients:
http://www.designdetector.com/demos/css-gradients-demo-1.php
I made a whole image this way!
http://www.designdetector.com/demos/css-house-2.html
Quick ‘n dirty hack( placed at the end of the HEAD and not tested ):
…
...
Not semantic but would be useful for quickly mocking stuff up for showing to clients etc – especially if you put the
s in with some DOM scripting..
Just waiting for multiple CSS backgrounds to arrive, they would make so many regular tasks (like fluid gradients!) so much easier..
…spending a mortifying amount of time creating the images…What if, after finishing, I needed to tweak the height? Or, God forbid, the color palette? My head was going to explode…
Although i’m a CSS newbie, and not quite ready to try this yet, the very idea that all those hours in Photoshop won’t be necessary just made my day. 🙂
Vera
100 is obviously human picked and arbitrary. The gradient breaks down with light colors in tall boxes. For best effect – with every shade possible – make your PNGs 256 pixels tall.
Here’s an alternative way to do the browser specific css if you don’t want to include separate stylesheets for each browser.
The Conditional Body Class
“http://www.puidokas.com/updating-my-css-for-ie7/”:http://www.puidokas.com/updating-my-css-for-ie7/
I want to like blendies but trying it in the Safari browser yields a question mark. See
http://www.pathuntwebdesign.com/example/
Good effort to reduce the file size and it will help for the good designing also. Now we can create gradient backgrounds in our site with faster downloading.
Thanks…
Let’s hope that setting a background size doesn’t become Good Practice like setting any other
tag’s size…that would be quite a burden.
Am I the only one thinking, _why is this on ALA_?
So instead of just using one tag with one line of CSS to insert a background gradient that’s somewhat larger than needed (and if it eventually bleeds out into a solid colour if text is resized is it really an issue?) I should add an extra img tag and an extra div tag to my mark up everytime I want to insert a background? Then I need how many extra hack riddled CSS rules to make it work?
The whole point of text resizing is to make your pages more accessible. When you use semantically incorrect code, propriety code, unneccesary mark up, a lot of decorative images with missing alt attributes, and numerous CSS hacks you’ve accomplished the exact opposite.
Not to mention search engines crawlers only index a certain number of characters, so all the exra code isn’t going to help your ranking at all.
Do I need to mention the modern web design principle of separation of structure and style?
As long as it looks pretty though because thats the important thing, right?
This is a non ‘solution’ to a non-issue.
When viewing the final bendy background example in firefox the alt tag text is showing up in the browser without the need to hover the mouse over the box.
Is there a CSS rule like img[attr=’alt’]{display:none;}
that can be added?
Otherwise any suggestions why this text is appearing and how it can be hidden???
Thanks muchly, Matthew. Ever since “Michael Lovitt’s”:http://alistapart.com/stories/pngopacity/ timely article, I’ve attempted to apply this very technique a couple of times in vain…I just never had enough patience to get it modular enough for practical application.
Not only are you laying out your explanation exquisitely, but you’re taking extra care to philosophically foreshadow better ways to make this work in any particular environment, without descending into a tangential discussion on tweaking.
Just hurry up and get the second part of this article out before Thanksgiving, and make my holiday weekend, _ALA_.
I just tried using this technique in a project I’m working on it noticed that it breaks in WebKit. Take a look and see what I’m talking about, it’s a bigger problem than with Opera.
I took a quick look at the problem and at first I thought it was just a simple overflow problem but it seems it’s a WebKit bug. The image element’s height is continuing outside of it’s parent element.
Putting overflow:hidden on image element’s parent keeps it from breaking really ugly but the gradient will still be broken. A bug report will be sent.
Thanks for your article. It’s very useful.
However,how can I put images in the boxes ?
I’ve tried to set the z-index to “2” and higher but it’s no help.
Please help me,thanks a lot!!
_”When viewing the final bendy background example in firefox the alt tag text is showing up in the browser without the need to hover the mouse over the box.”_
This isn’t my experience, with Firefox 2 on XP.
*NOTE TO EDITORS*: Please fix the missing end tag for the code on the previous page of comments! It is turning everything after into Courier, including the side bar!
Please *don’t add @alt@ attribute to decorative images*! It should be an empty string:
![]()
“guidelines on alt by J.Korpela”:http://www.cs.tut.fi/~jkorpela/html/alt.html
What happened to separating content from presentation? It’s a great technique, but using
s as backgrounds?
Hmmm…
Cool technique. Although the scaling of images sends a cold chill down my spine, it stinks of the 1px transparent gif trick for object spacing ( which was only ever used by the lazy and incompotent ). Resizing images forces the browser to waste cpu cycles doing what it’s not really very good at. Given all the other stuff we are forcing browsers to cope with I can’t see how that’s a good idea. And you just know that somebody is going to put this in a div which they will then resize dynamically. Oh the horror!!!
It’s very interesting and I guess there’s no limits to what’s can be done with css!
It looks pretty, but from a semantic perspective, adding an image for purely presentational purposes is iffy. Screen reader users will experience the annoyance of having their reader say “image” each time one of these boxes is “read out” aloud.
AS of IE 5, you can also produce gradients exclusively with Style Filters. The gradient is exclusively HTML and CSS. it does not require an image
#48 (and others with screenreaders)
Havent you heard about setting the media in the css include?
_”AS of IE 5, you can also produce gradients exclusively with Style Filters.”_
IE5.5 to be precise.
_”The gradient is exclusively HTML and CSS. it does not require an image.”_
And only works in one single browser, Internet Explorer, available for one single platform, Windows. The web has moved on. People use Macs. People use Linux. People use mobile phones. Browsers today include a wide range of available programs. Anything IE-only is to be completely avoided (unless your page degrades nicely without the IE-only special effects).
It’s a shame, because filters were one of the coolest things to hit the web. You can use them to rotate images for instance, so only one gif is needed for a four-corner frame. Or have a black and white photo turn to colour on hover just by using a filter.
Is it really worth it? Is it really worth all the haggle and all that messy markup/CSS-code to save in a few bytes of image-files? I think not. I’d rather preffer ten image-files weighing a few kilobytes rather than having all that extra code to mess up my stylesheet and markup, especially on a large webpage with a complex layout.
You could do it server side (or probably with JS), though, but that again would leave far more work than just making it as images in the first place.
Nice method for experimenting, understanding and learning, but I dont think i will be using it a lot.
Learning CSS with this type of good article and demo is fun… great job!!
Thanks Matthew O’Neill.
Why does this break in IE 6 when I remove the float:left from the .box? (It will still work in Firefox.)
nice article, and good concept to apply.
The part to make PNG work in IE using AlphaImageloader seems to be misplaced though.
Why would one require a filter to do other filters’ job, that too using external images?
please look up http://msdn.microsoft.com/workshop/author/filter/reference/filters/gradient.asp
My idea will be to get gradients in IE without using any imges, keep the PNG gradeient of FF and other browsers though.
Opera doesn’t like padding on the containing div–it seems to still apply the padding to the absolutely positioned image, but on the right side of the div. Removing the padding or placing it on another element (such as a nested span) apparently fixes this.
An example: http://prisoner34.com/blendy/
Sorry, but this time it wasn’t 🙁 I frequently find ALA articles interesting, even when I can’t find them an inmediate use. But not this time.
When I became aware of what a PNG can do I tried this trick, but found most of the problems already mentioned in the article and the comments. But the worst, for me, is that it isn’t enough to mix a color with white or black to make it look good!
Considering that any 256×256 2-color PNG linear gradient is about 860 bytes long and that I can create it with 7 mouse clicks and a filename, I doubt I’ll bother with the second part of the article.
… some Browsers don’t support the transparency of PNGs?
I can see maybe, maybe using this for mock-ups, but with today’s graphic tools, creating high-quality gradients is easy.
I really suggest avoiding this technique and making backgrounds with what they are intended: the background property. At least the background property is cross-platform and has very few issues with various layout techniques (floats, absolute positions, etc) where this method can easily break down.
I applaud the creativity, but it has a major down side. The img elements in the markup are not really content, but are shown as such by web clients that aren’t css aware or that have css turned off.
We needed scalable background images for a project several months ago and went with this technique. Our web site navigation now looks horrible in non-css browsers, like cell phones, lynx, or even ie/win in accessibility mode. it also probably makes users of screen readers unhappy.
Its a neat hack, but not a good production solution.
It uses a CSS hack.
I never have used hacks in any of my css. Never will.
I will see if I can come up with the same technique and no hacks.
I mean, it works – yeah. And it’s a pretty good idea. Very original thought process. It just seems like so much extra work to achieve something you can do with a couple of seconds in photoshop with the gradient tool.
Great idea, really. Just seems a bit excessive to make a gradient.
I recently rediscovered the Power of PNG 24bit transparencies after running some wonderful tests in FireFox and went ga-ga over it. Of course I repeated the tests in IE 6 and wanted to cry… support for this is non existent without going above and beyond compliant mark up for CSS, I wonder how long IE7 will take to hit the masses hard with Windows Vista out. Then we can go Nuts!
I must say that this technique is really great. It also inspired me to create blendy tabs, to use for site navigation. Take a look at:
http://www.boriskuzmic.com/index.php?p=projects_css_js