CSS Gradients

By  on  
CSS Gradients

With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome, we can safely implement them in our websites.  Let's look at the basics of CSS gradients:  their syntax, browser support, and fallbacks.

Gradient Terms and Ideas

Gradients provide a method to, over a customizable amount of space, transition from one color to another.  Gradients come in two variants:  linear (one consistent gradient) and radial (circular).  While gradients are obviously graphical elements, they're simplistic in creation which makes them outstanding candidates for simple, programmatic creation via CSS.  CSS3 introduced CSS gradients but their implementation took longer than we all wanted.

CSS Linear Gradient Syntax

The linear gradient implementations are different in each browser but there is a set standard:

background-image: linear-gradient( || ,]? ,  [, ]* )

The first argument is the point of which to start the gradient or the angle at which the gradient should be drawn.  The subsequent arguments are "color stops" along the gradient.  Two color stops are required (start and end), but any number of color stops can be added for increased customization of the gradient.  Color stops can include just a color or a color and percentage or point:

/* old:  color-stop(percentage/amount, color) */
color-stop(0.20, red)

/* current:  color _ percentage/amount */
#dea222 20%

As is the case with most newer, advanced CSS capabilities, each browser tends to provide its own implementation.  WebKit, for example, even has multiple syntaxes.  The following code snippet should cover all the bases for a basic, top-to-bottom linear gradient:

#example1	{
	/* fallback */
	background-color: #063053;
	/* chrome 2+, safari 4+; multiple color stops */
	background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0.32, #063053), color-stop(0.66, #395873), color-stop(0.83, #5c7c99));
	/* chrome 10+, safari 5.1+ */
	background-image: -webkit-linear-gradient(#063053, #395873, #5c7c99);
	/* firefox; multiple color stops */
	background-image: -moz-linear-gradient(top,#063053, #395873, #5c7c99);
	/* ie 6+ */
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#063053', endColorstr='#395873');
	/* ie8 + */
	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#063053', endColorstr='#395873')";
	/* ie10 */
	background-image: -ms-linear-gradient(#063053, #395873, #5c7c99);
	/* opera 11.1 */
	background-image: -o-linear-gradient(#063053, #395873, #5c7c99);
	/* The "standard" */
	background-image: linear-gradient(#063053, #395873, #5c7c99);
}

Note that a basic background-color is provided first.  This background-color is a fallback for browsers that have not yet implemented CSS gradients.  The CSS gradient spec allows for degree'd CSS gradients instead of basic top-to-bottom gradients.  These can be accomplished with the following syntax:

#example2	{
	/* fallback */
	background-color:#063053;
	/* chrome 2+, safari 4+; multiple color stops */
	background-image:-webkit-gradient(linear, left bottom, right top, color-stop(0.32, #063053), color-stop(0.66, #395873), color-stop(0.83, #5c7c99));
	/* chrome 10+, safari 5.1+ */
	background-image:-webkit-linear-gradient(45deg, #063053, #395873, #5c7c99);
	/* firefox; multiple color stops */
	background-image:-moz-linear-gradient(45deg, #063053, #395873, #5c7c99);
	/* ie10 */
	background-image: -ms-linear-gradient(45deg, #063053 0%, #395873 100%);
	/* opera 11.1 */
	background-image: -o-linear-gradient(45deg, #063053, #395873);
	/* The "standard" */
	background-image: linear-gradient(45deg, #063053, #395873);
}

Or how about a more ... colorful CSS gradient?  Let's do a rainbow gradient:

/* example 3 - linear rainbow */
#example3	{
	/* fallback */
	background-color:#063053;
	/* chrome 2+, safari 4+; multiple color stops */
	background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0.20, red), color-stop(0.40, green), color-stop(0.6, blue), color-stop(0.8, purple), color-stop(1, orange));
	/* chrome 10+, safari 5.1+ */
	background-image:-webkit-linear-gradient(red, green, blue, purple, orange);
	/* firefox; multiple color stops */
	background-image:-moz-linear-gradient(top, red, green, blue, purple, orange);
	/* ie10 */
	background-image: -ms-linear-gradient(red, green, blue, purple, orange);
	/* opera 11.1 */
	background-image: -o-linear-gradient(red, green, blue, purple, orange);
	/* The "standard" */
	background-image: linear-gradient(red, green, blue, purple, orange);
}

A quick note about Internet Explorer's gradient support.  Internet Explorer's filter and -ms-filter syntax takes precedence over the newer -ms-linear gradient syntax.  It's best to use IE conditional comments to create reliable gradients:

<!--[if lt IE 10]>
<style>
.gradientElement {
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#063053', endColorstr='#395873');
	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#063053', endColorstr='#395873')";
}
</style>
<![endif]-->

Not ideal but reliability is important when designing a website.

CSS Radial Gradients

Radial gradients are unlike linear gradients because they don't move from one simple direction to another;  they start with a center-point and move outward at 360 degrees.  Radial gradients are not supported by Internet Explorer at this time, and the browsers that do support radial gradients have had significantly different syntaxes...I'm looking at you, WebKit! WebKit has, however, overhauled their radial gradient syntax.  Here's a brief look at the current-but-soon-to-be-legacy radial gradient code:

/* basic */
background-image: -webkit-gradient(radial, center center, 0, center center, 220, from(orange), to(red));
/* color stops */
background-image: -webkit-gradient(radial, center center, 0, center center, 220, color-stop(0.20, red), color-stop(0.40, green), color-stop(0.6, blue), color-stop(0.8, purple), color-stop(1, orange));

WebKit recently announced its new syntax for creating radial gradients which happens to fall in line with Firefox's implementation:

radial-gradient( [ || ,]? [ || ,]? , [, ]*)

This radial gradient syntax works in Firefox 4 and the WebKit nightlies.  There are a number of size constants available with radial gradients:

  • closest-side: The gradient's shape meets the side of the box closest to its center (for circles) or meets both the vertical and horizontal sides closest to the center (for ellipses).
  • closest-corner: The gradient's shape is sized so it exactly meets the closest corner of the box from its center.
  • farthest-side: Similar to closest-side, except the shape is sized to meet the side of the box farthest from its center (or vertical and horizontal sides).
  • farthest-corner: The gradient's shape is sized so it exactly meets the farthest corner of the box from its center.
  • contain:  A synonym for closest-side.
  • cover:  A synonym for farthest-corner.

A basic usage of a radial gradient would look like:

#example4 {
	background-image: -moz-radial-gradient(orange, red);
	background-image: -webkit-gradient(radial, center center, 0, center center, 220, from(orange), to(red)); /* old */
	background-image: -webkit-radial-gradient(orange, red); /* new syntax */
	background-image: radial-gradient(orange, red);
}

Note that no positioning or size has been given -- simply two color stops to it over the course of the gradient.  Any number of color stops can be used so a simple rainbow gradient would look like:

#example5 {
	background-image: -moz-radial-gradient(red,green,blue,purple,orange);
	background-image: -webkit-gradient(radial, center center, 0, center center, 220, color-stop(0.20, red), color-stop(0.40, green), color-stop(0.6,blue), color-stop(0.8,purple), color-stop(1,orange)); /* old */
	background-image: -webkit-radial-gradient(red, green, blue, purple, orange); /* new syntax */
	background-image: radial-gradient(red, green, blue, purple, orange);
}

A more customized radial gradient with positioning and detailed color stops would look like:

#example6 {
	background-image: -moz-radial-gradient(45px 45px 45deg, circle cover, yellow 0%, orange 100%, red 95%);
	background-image: -webkit-radial-gradient(45px 45px, circle cover, yellow, orange);
	background-image: radial-gradient(45px 45px 45deg, circle cover, yellow 0%, orange 100%, red 95%);
}

Note that my examples are using hex colors and px units.  You may use any of the color constructs or measuring units with your gradients.

CSS Gradients:  Tips and Tricks

CSS gradients are quite valuable but can be difficult to implement.  Even when you've got the gradient you want, browser support can be different.  Here are a few tips for using CSS gradients:

  • Want opacity within your gradients?  Use rgba colors.
  • Always use a fallback background so that clients that doesn't support gradients aren't hung out to dry.
  • Both Firefox and WebKit-based browsers provide prefixed repeating-linear-gradient and repeating-radial-gradient capabilities.  An example of usage:

    #example7 {
    	background-image: -moz-repeating-linear-gradient(top left -45deg, green, red 5px, white 5px, #ccc 10px);
    	background-image: -webkit-repeating-linear-gradient(-45deg, green, red 5px, white 5px, #ccc 10px);
    }
    
  • If gradient are critical (i.e. charting, animation, etc.), I highly recommend using Dojo's GFX library, which is a masterpiece of vector graphic creation.  GFX also allows for radial gradients in Internet Explorer!

CSS Gradient Fallbacks

Older browsers like Internet Explorer 6 and 7, along with Opera and older versions of Firefox, don't support CSS gradients so the best fallback for such cases is defining a regular background property with a color of your choice:

/* example 1 - basic */
#example1	{
	/* fallback */
	background-color:#063053;
	/* gradients below */
}

Another option would be to create the gradient a browser that supports CSS gradients, take a screenshot, cut an image of the gradient, and use conditional CSS for the browsers that didn't support CSS gradients.

CSS gradients are yet another step in the evolution of CSS, mixing basic style programming with basic design principles.  Now that CSS gradients are supported in most A-grade browsers, we can start to use them with more confidence.

Recent Features

  • By
    fetch API

    One of the worst kept secrets about AJAX on the web is that the underlying API for it, XMLHttpRequest, wasn't really made for what we've been using it for.  We've done well to create elegant APIs around XHR but we know we can do better.  Our effort to...

  • By
    Write Simple, Elegant and Maintainable Media Queries with Sass

    I spent a few months experimenting with different approaches for writing simple, elegant and maintainable media queries with Sass. Each solution had something that I really liked, but I couldn't find one that covered everything I needed to do, so I ventured into creating my...

Incredible Demos

Discussion

  1. I’ve found a CSS3 pattern gallery at:
    http://leaverou.me/css3patterns/

    Quite awesome in my opinion…

    • Great patterns! I bookmarked these!

  2. Tim Scully

    A good reference for css gradients though, very informative and thorough!

  3. I didn’t know you could repeat them yet. @Alex, great work on the pattern’s, they blew my mind.

  4. I’ve been using css gradients in my sites for about a year now. Because IE7+ supports them, you can use them basically anywhere you want, so it really cut down on the amount of images you need.

    Though the markup for cross-browser gradients is about 8 lines…

    • Yeah, that 8-line bit sucks, and it probably wont go anywhere anytime soon.

    • alpha123

      Hey, it’s better than several kb of images. Just use something like SASS to make it suck less, typing the same thing 8 times with slight variations isn’t how I want to spend my time. :P

      Oh, and you should probably use _filter: for IE 6+ so as not to confuse other browsers.

  5. Kim

    I’ve been trying to set up a body background gradient. It’s working well on all browsers on my mac. But when I test on my PC, the gradient that looks fine in Chrome or Firefox on my mac, turns into weird banded repeating elements on my PC (small bands across browser windiw in FF, wider/taller bands in Chrome). Looks nice and smooth on IE though. Would anyone have any ideas why I’m seeing this problem?
    Here’s my code:

    background-repeat: no-repeat;
     background: #CCEEF6; /* for non-css3 browsers */
     background-image: -o-linear-gradient(#FFF, #00A9D2); /* for opera 11.10+ */
     background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#00A9D2)) fixed; /* for webkit browsers */
     background: -moz-linear-gradient(top, #FFF, #00A9D2) fixed; /* for firefox 3.6+ */
     filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='white', endColorstr='#00A9D2', GradientType=0); /* for IE 5.5-7 */
     -ms-filter:  progid:DXImageTransform.Microsoft.Gradient(startColorstr='white', endColorstr='#00A9D2', GradientType=0); /* for IE8 */
    

    thanks,
    kim

    • This is most likely due to the color profile handling in Windows.

      I put a test page together with the code you posted and tested it in FF4 and IE6 (don’t ask) in Windows XP. I could see some banding, but only by looking closely. I imagine that as the body background, if it extended the entire way down the page it would band pretty bad. You could get around this by using a color stop at a certain pixel height to make the gradient only extend down the page about 500 pixels. You can’t achieve this with the filter for IE, but who cares if they get banding, amiright?

    • Kim

      Thanks for the response, Brad.

      I was just coming back to post what I’ve found was causing the problem (which you also came up with).

      The code is fine.

      The problem was that I was connecting to my PC via remote desktop and I have now discovered that 16bit color depth is apparently the default for that.
      Safari and IE showed smooth gradients anyway, so when Chrome and FF did not, I was tricked into thinking it was some issue with the code or those browsers.

      Thanks again for your response!

  6. There’s a great collection of CSS gradients, box shadows, and transforms available here:

    http://code.google.com/p/css3-graphics/

    Be sure to check them out!

  7. alelo
    background-color: green; background-image: -webkit-repeating-linear-gradient(45deg, transparent, transparent 33px, rgba(255,255,255,1) 36px, rgba(255,255,255,1) 70px);

    is funny, on my left screen its rendered well, but on my second it becomes edges (both 1680×1050, just other ” size)

    • alelo

      it gets edges damn, dont write while testing stuff ~~

  8. Andrew

    I’ve found this site to be useful for developing gradients for use on the iPad (and really most browsers).

    http://westciv.com/tools/gradients/

    • alpha123

      I do too, however it only generates them for Gecko and WebKit (not to mention it has separate generators for them <_<), and it uses the old WebKit syntax which is really bulky.

  9. I’ve noticed that, in IE8 (standards mode, HTML5 doctype), if you try to apply a gradient to an A tag, it won’t work until you put a display:inline-block on it.

    Also, hello from Milwaukee!

  10. How do I create an effect where only the middle course

  11. Maïs

    Correct me if i’m wrong, but IE10 dosen’t need the -ms prefix, it’s use the standard implementation.

  12. Just a quick question. Can I use gradient styling on actual text using CSS?

  13. rud

    I tend to use this for my gradients, works find for me so far.. http://www.colorzilla.com/gradient-editor/

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!