Using a CSS gradient and a background image on the same element

posted by on 2010.09.25, under CSS
25:

I’ve spent the last 2 weeks working on the next version of the tmg website and I’ve been having a lot of fun using lots of CSS3.

One of the problems I ran into was having a background image and a css gradient on the same element. CSS gradient’s aren’t a part of the official W3C backgrounds and borders spec, but they have been implemented by Webkit (Safari and Chrome, amongst others) and Mozilla (Firefox) using vendor prefixes. The trouble with things that aren’t in the spec is that it is a bit harder to find the relevant documentation.

These won’t work

The problem stems from the fact that gradients are specified as a background-image, which means they override any previously declared background-image. If you do it in the opposite order, the background-image will override the gradient.
I’ve simplified the CSS here, but if you want to see the full code for each example just fire up Firebug or your browser’s built in developer tools.

.example1 {
	background-image: url(../images/plus.png);
	background-image: -moz-linear-gradient(top,  #cbe3ba,  #a6cc8b); /* for firefox 3.6+ */
	background-image: -webkit-gradient(linear, left top, left bottom, from(#cbe3ba), to(#a6cc8b)); /* for webkit browsers */
}
 
.example2 {
	background-image: -moz-linear-gradient(top,  #cbe3ba,  #a6cc8b);
	background-image: -webkit-gradient(linear, left top, left bottom, from(#cbe3ba), to(#a6cc8b));
	background-image: url(../images/plus.png);
}
example 1
example 2

This does work

Well it turns out that it is actually very easy to apply both a gradient and a background image to the same element. You can read about the Mozilla implementation and Safari (Webkit) implementation on their websites, or you can carry on reading here.
The trick is to set the gradient and the background-image using the multiple background syntax which is part of the W3C spec.

.example3 {
	background-image: url(../images/plus.png), -moz-linear-gradient(top,  #cbe3ba,  #a6cc8b);
	background-image: url(../images/plus.png), -webkit-gradient(linear, left top, left bottom, from(#cbe3ba), to(#a6cc8b));
}
example 3

How about combining the -moz- and -webkit- backgrounds?

Using this new found information, the obvious question is “can we use the multiple background syntax to declare the gradient for webkit and mozilla at the same time?”. Let’s find out.

.example4 {
	background-image: url(../images/plus.png), -moz-linear-gradient(top,  #cbe3ba,  #a6cc8b), -webkit-gradient(linear, left top, left bottom, from(#cbe3ba), to(#a6cc8b));
}
example 4

Rather annoyingly that doesn’t work. I would have thought that each browser would ignore the vendor prefixes it doesn’t know, but it looks like that only works for CSS property names, not values. Although thinking about it, that’s not what’s going on with the other examples because the vendor prefix is on the value there and not the property name.

Whatever the reason, it looks like we’ll have to stick to multiple, vendor-specific lines for the time being. Hopefully CSS gradients will be incorporated into the spec soon so we will only have to declare them once.

pagetop