So, CSS3 gradients are cool. Sure, you need to use a couple of different vendor prefixes but the syntax is pretty nice

.my-gradient {
    background: -moz-linear-gradient(top, #00b7ea 0%, #009ec3 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#00b7ea), color-stop(100%,#009ec3)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, #00b7ea 0%,#009ec3 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, #00b7ea 0%,#009ec3 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top, #00b7ea 0%,#009ec3 100%); /* IE10+ */
    background: linear-gradient(to bottom, #00b7ea 0%,#009ec3 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00b7ea', endColorstr='#009ec3',GradientType=0 ); /* IE6-8 */}

The only caveat here is the filter declaration for IE. You’re limited to a straight top-to-bottom linear gradient (no multi-stops) but more importantly, the gradient background will overflow any border radius you may have defined.

No problem, IEs 7 and 8 don’t support border-radius anyway but what about IE9? The solution…

SVG background images

The standard SVG gradient background definition looks something like this

<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
  <linearGradient id="grad-ucgg-generated" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%">
    <stop offset="0%" stop-color="#00b7ea" stop-opacity="1"/>
    <stop offset="100%" stop-color="#009ec3" stop-opacity="1"/>
  </linearGradient>
  <rect x="0" y="0" width="1" height="1" fill="url(#grad-ucgg-generated)" />
</svg>

You can then base64 encode this and set it as a data URI background image which will work beautifully in IE9. For example

background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2l...);

Doing it with LESS

I’ve been using LESS lately and was almost going to move to SASS + Compass in order to achieve the above but found a way to stick with LESS. Enter the base64DataUriBackground mixin. This can be made very simple if your LESS parsing environment has access to the btoa() function.

.base64DataUriBackground (@encode, @type: ~"image/svg+xml") {
    @dataUriPrefix: ~"url(data:@{type};base64,";
    @dataUriSuffix: ~")";
 
    // with btoa()
    @b64DataUri: ~`(function(a,b,c){return a+btoa(b)+c})('@{dataUriPrefix}','@{encode}','@{dataUriSuffix}')`;
 
    // without
    @b64DataUri: ~`(function(a,b,c){function e(a){a=a.replace(/\r\n/g,'\n');var b='';for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);if(d<128){b+=String.fromCharCode(d)}else if(d>127&&d<2048){b+=String.fromCharCode(d>>6|192);b+=String.fromCharCode(d&63|128)}else{b+=String.fromCharCode(d>>12|224);b+=String.fromCharCode(d>>6&63|128);b+=String.fromCharCode(d&63|128)}}return b}function f(a){var b='';var c,f,g,h,i,j,l;var m=0;a=e(a);while(m<a.length){c=a.charCodeAt(m++);f=a.charCodeAt(m++);g=a.charCodeAt(m++);h=c>>2;i=(c&3)<<4|f>>4;j=(f&15)<<2|g>>6;l=g&63;if(isNaN(f)){j=l=64}else if(isNaN(g)){l=64}b=b+d.charAt(h)+d.charAt(i)+d.charAt(j)+d.charAt(l)}return b}var d='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';return a+f(b)+c})('@{dataUriPrefix}','@{encode}','@{dataUriSuffix}')`;
 
    background: @b64DataUri;
}

Here’s an example gradient mixin

.gradient (@gradient-top, @gradient-bottom) {
    @svg: ~'<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="grad-ucgg-generated" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="@{gradient-top}" stop-opacity="1"/><stop offset="100%" stop-color="@{gradient-bottom}" stop-opacity="1"/></linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#grad-ucgg-generated)" /></svg>';
 
    .base64DataUriBackground(@svg);
 
    background: -moz-linear-gradient(top, @gradient-top 0%, @gradient-bottom 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@gradient-top), color-stop(100%,@gradient-bottom)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, @gradient-top 0%,@gradient-bottom 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, @gradient-top 0%,@gradient-bottom 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top, @gradient-top 0%,@gradient-bottom 100%); /* IE10+ */
    background: linear-gradient(to bottom, @gradient-top 0%,@gradient-bottom 100%); /* W3C */
    filter: ~"progid:DXImageTransform.Microsoft.gradient( startColorstr='@{gradient-top}', endColorstr='@{gradient-bottom}',GradientType=0 )"; /* IE6-8 */
}

One final thing you will need to do is disable the filter declaration for IE9 (and above). You can achieve this simply through a conditional stylesheet

<!--[if gte IE 9]>
  <style type="text/css">.my-gradient-class{filter: none;}</style>
<![endif]-->

All CSS examples courtesy of the most awesome Ultimate CSS Gradient Generator.