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.

comment

Thank you, that helps me a lot, it works perfectly but I ran into another problem. Of course Internet Explorer 8-. When you apply:

filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#ffffff');

It will remove any background paramenters and values. Don’t have new IE9 at work to see how it works.

But If anyone has a suggestion that would be awesome. Most of our customers use IE and believe me they still with IE6. I know, I know awful!

Thanks again for your post!

Rafael ( December 3, 2010 at 5:15 pm )

Hi Rafael – thanks for your comment.

In the site where I used this technique I was able to get around this for IE by having the gradient as background on a li element and the plus sign on a nested a element.

You could maybe use a nested div or span to make it work.

I haven't checked IE9, but I imagine the non-prefixed W3C CSS rules will work fine.

David Owens ( December 6, 2010 at 1:21 pm )

Thanks for the helpful post!

I was still stuck on how to specify repeats and positioning for the background image while also using gradients; here's what works for that:

<code>

background: url(background.png) no-repeat left bottom, -moz-linear-gradient(100% 100% 90deg, #2F2727, #1a82f7) ;

background: url(background.png) no-repeat left bottom, -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1a82f7), to(#2F2727));

</code>

Hope that helps someone else who's stumped!

Jack Aponte ( January 12, 2011 at 11:00 pm )

First off, awesome article. I didn’t realize this was possible and I’ve often wrapped elements in an extra div to pull of the effect but this way is much cleaner.

However, I’m having a bit of trouble getting this fix to work. Whenever I specify no-repeat it stops working (no back ground image and no gradient). If I leave out no-repeat the gradient pulls in but then I have tons of repeating arrows within my element.

Below is my code. Any ideas on where I’m screwing it up? Thanks again for the post David.

background-image: url(../images/arrow_toggle.png) no-repeat, -webkit-gradient(linear, left bottom, left top, color-stop(0.43, rgb(201,201,201)), color-stop(0.72, rgb(219,219,219)));

Jared Polivka ( August 4, 2011 at 10:42 pm )

Hi Jared. When you add “no-repeat” to the rule you are switching from using “background-image” to using the “background” shorthand syntax. “no-repeat” is a value for the “background-repeat” rule.

If you swap “background-image” for just “background” everything should work fine.

David ( August 5, 2011 at 1:38 am )

hi David, simply don’y work for me, my code

G + B

.example1 {
width: 300px;
height: 225px;
background-image: url(ping.png);
}
.example2 {
width: 300px;
height: 225px;
background-image: -moz-linear-gradient(top, red, yellow);
background-image: -webkit-gradient(linear, left top, left bottom, from(red), to(yellow));
}
.example3 {
width: 300px;
height: 225px;
background-image: url(ping.png), -moz-linear-gradient(top, red, yellow);
background-image: url(ping.png), -webkit-gradient(linear, left top, left bottom, from(red), to(yellow));
}
.example4 {
/* use shorthand */
width: 300px;
height: 225px;
background: url(ping.png), -moz-linear-gradient(top, red, yellow);
background: url(ping.png), -webkit-gradient(linear, left top, left bottom, from(red), to(yellow));
}

Show background-image

Show Gradient

Show only background-image

Show only background-image

whtas wrong? tested in Firefox 8/Safari5 (win7) and Chrome 15
any idea
thanks

emprear ( December 9, 2011 at 12:01 am )

This is a great article, thank you very much. Done a bit of tinkering with this myself and got this to work in ie8 like so.

filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=’#ed0000′, endColorstr=’#ba0101′,GradientType=0 ),
progid:DXImageTransform.Microsoft.AlphaImageLoader(
src=’./?a=406091′); /* IE6-9 */

hope this helps.

thanks

Luke Mclean ( December 16, 2011 at 1:46 pm )

Thanks for your post and it is a great article. I was doing a similar testing a while ago, hope it helps as well – http://iroylabs.blogspot.com/2011/09/gradient-test-gotcha-ie-vs-other.html

Roy ( February 22, 2012 at 12:24 am )

PIE.htc works for the IE problem, IE is such a headache, spent hours on it, no image will show in IE6-9
http://css3pie.com/documentation/supported-css3-features/#pie-background
hope this helps save someone hours of time
cheers, L

Leah ( July 23, 2012 at 3:52 pm )

Awesome work! Now, any way to use that plus.png image from a sprite? My block here is that I need to specify the width and height for a sprite to function properly. Plus, I’m locked in to the html I’m using because it is global across multiple sites.

Brad Hutchison ( August 14, 2012 at 11:23 pm )

Hi Brad. Do you mean the width and height of the image, or the width and height of the element whose background you’re setting?

Can you set something up on http://jsfiddle.net so we can see what you have?

David ( August 14, 2012 at 11:54 pm )

Thanks a million. This works great! Exactly what I wanted, and is nice and clean.

Fiachra ( January 18, 2013 at 12:29 pm )

First of all thank you so much for your time in explaining. Really useful info. But…

Does the above code work in IE9 because when I view the page I couldn’t see the gradients for all the example?

Kasi ( February 22, 2013 at 9:34 pm )

    Hi Kasi,

    I need to update the code examples at some point. They’re pretty old and those prefixed versions will only work in Firefox and Webkit.

    In the meantime, you can take a look at the Mozilla article about cross-browser CSS3 gradient syntax. It also includes some of the history and how it has changed since I wrote the article.

    David ( April 26, 2013 at 1:53 pm )

Please Leave a Reply

TrackBack URL :

pagetop