I’m beginning to get exhausted by the collective branding of the newest batch of CSS styles as “CSS3.” The title implies some form of unified vision that looks towards a horizon upon which perches a promised land covered in roses and ivory towers. This paradise, in this vision, is a grand land which the modern browsers will enter, hand-in-hand, skipping together with a common purpose.
CSS3 Heaven?
It sounds very idyllic and wondrous.
Instead, CSS3 as I see it is a dark realm that peeks out from a trench in the deepest part of the coldest sea, guarded by pale wriggling squid the size of airliners that callously reach out at brave divers, consuming them with confusing and conflicting implementations. Each module is clustered next to its fellows, clutching to the back of the underwater prison like an infestation of oily warts, filled with syntax to the point of bursting. At times, the mammoth guardian squid, each stamped with names like “Webkit” and “Gecko” dip down and rip pieces off these structures, consuming conflicting syntaxes and fueling alternate visions of what this decaying city is supposed to resemble.
The True Vision of CSS3?
Lest you mistake my metaphor, I am glad to see CSS3 features appearing in more and more browsers with each new version. I even hold out hope that in its ninth version, Internet Explorer will embrace some of these features. But let’s become clear about it: CSS3 isn’t a single target for browsers to hit. There’s dozens of modules being birthed and slain in primordial ooze at any given moment, many of which see early adoption by competing browsers with competing syntax. The whole thing starts to give me a headache at times.
Today’s case in point is CSS Gradients. As styles go its purpose is very sweet: allowing you to make gradient backgrounds on various page elements, making for some really stunning (or potentially hideously cloying) visuals. With the release of 3.6, Firefox has joined Webkit (Safari and Chrome) in supporting this bit of CSS wizardry. And, despite being the kid in the short bus, Internet Explorer actually supports limited gradients with its custom filter system.
The problem is that each browser is implementing the feature in its own way, with varying syntax that results in overlapping but not identical abilities in what kind of gradients can be produced. Yes, in each case we’re using browser-specific CSS extensions (with the –moz and –webkit prefixes), but even at this state it’d be a lot more convenient as a designer if there was a little more agreement on how we were adding these colorful swaths to our pages.
What I’m getting at is that CSS gradients are very cool, and prone to make your brain hurt in certain circumstances. Firefox and Webkit each tackle the issue differently. For very basic gradients these differences are relatively minor and easy to plan for. With more complicated gradients there can arise situations where one browser is capable of creating the desired effect but the other is not.
For that reason, I’m intentionally limiting this first dip into the gradient pool to simple, linear gradients. I want to make it clear; we’re just putting our toes in the water here. There’s a whole lot more, and if my brain keeps in one piece I’ll be creating additional installations of tutorials on this topic.
Before I tackle example code, I need to first explain three concepts that are important in gradients: type, direction and color stops.
Gradient Type
There are two types of gradients (at present): linear and radial. A linear gradient is one that changes colors in a straight axis across the object in question. A radial gradient is one that changes colors in a circular (well, oval) pattern instead. As I said earlier, we’re only covering linear gradients today.
Gradient Direction
Gradients also require a direction, which, as you’d guess, controls the direction of the axis of the color change. How this direction is established varies a bit from browser to browser. Firefox chooses an origin and an angle, in Webkit you choose an origin point and a destination point. In Internet Explorer’s gradient filter you can only choose one of the four cardinal directions as the origin, and it automatically makes a straight axis to the opposing edge. I’ll explain this in full detail further along, but this is one of the conflicting syntax issues that really begin to make working with gradients in CSS annoying.
Color Stops
Lastly, there’s the concept of a color stop. Think of it as a pole or stop sign along the axis of a gradient that dictates what color should be present at that point. The browser blends the colors between that point and the next stop as needed to create a smooth gradient between those points. There can be multiple color stops in a gradient (except in IE) and the first and last color stops represent what color the beginning and ending colors will be on the gradient (even if those stops aren’t at the beginning and end of the gradient’s axis).
A Basic Gradient
Ok, now that I’ve confused you, let’s do a very simple starting gradient. Let us suppose that we want a button that is yellow up top, but fades to red at the bottom. Such a button’s CSS would be:
button{
background: -moz-linear-gradient(top, yellow, red);
background: -webkit-gradient(linear, 0 top, 0 bottom, color-stop(0, yellow), color-stop(1, red));
}
That example code (which you can view here) works in both Firefox (3.6 and higher) and Webkit browsers. The top line is Firefox’s syntax; the bottom is Webkit’s. You can include both, and each browser will ignore the rule that it doesn’t understand.
As you might notice, these rules look very different from one another. The common element, however, is that both browsers allow the use of a valid color name (in addition to normal color codes). Other than that, it gets very different really quickly.
Here’s how Firefox’s syntax for linear gradients work:
-moz-linear-gradient( [point] [angle], [stop], [stop], etc)
The minimum requirements for a valid gradient in this syntax are an origin point and at least two color stops. The origin point uses the same syntax as background-position (or –moz-transform-origin), thus expressible in pixels, “left”, “top” etc.
A color stop requires at least the color value (such as “red”, “#ff0000” or RGBA(255, 0, 0, 1)) and optionally a stop position (a percentage between 0% and 100% along the gradient’s axis). If no stop positions are supplied, the stops will be evenly spaced out along the gradient. (This would be written as “red 50%” or “rgba(255, 0, 0, 1) 50%”). At least two stops are required, but you can continue to add more if you desire.
The angle, which is optional, can be expressed in degrees (90deg), grads (100grad) or radians (1.571rad). If an angle isn’t provided, Firefox assumes its 180 degrees from the origin. Note that if you include an angle, it’s not separated from the origin by a comma (example: -moz-linear-gradient(top 45deg, red, blue);)
Now, to my eyes, Firefox’s system is both straightforward and blissfully sparse. Now let’s look at how it works with Webkit. Here’s the syntax:
-webkit-gradient([type], [point], [point], [stop], [stop], etc)
The minimum requirements for a valid gradient for Webkit are the type (linear or radial), and in the case of a linear gradient the origin and ending points (which are expressed in the same fashion as background-positions such as “left top”), and at least two color stops.
You’ll note there’s no angle option. You have to pick both the start and ending points.
The color stops in Webkit are a good deal chattier than those in Firefox. Like the Firefox ones they do allow for color names, hex codes, or RGBA codes. But instead of expressing the stop’s position along the axis in percentages, it’s done as a decimal value between 0 (the beginning) and 1 (the end). Lastly, they like to expressly add “color-stop” to the syntax for each one.
Just in case you get confused, I guess.
Examples are “color-stop(0.5, red)”, “color-stop(0.5, #ff0000)” or “color-stop(0.5, rgba(255, 0, 0, 1))”.
Ok, there, I’ve explained it all. Make sense yet?
No, somehow I doubted it would. Here, then, are several examples of doing different types of gradients in both browsers.
Simple Left to Right
button{
background: -moz-linear-gradient(left, #f00, #000);
background: -webkit-gradient(linear, left 0, right 0, color-stop(0, #f00), color-stop(1, #000));
}
Left to Right Where the Second Color is At Full Value 1/3 of the way through
button{
background: -moz-linear-gradient(left, #f00 0%, #000 33%);
background: -webkit-gradient(linear, left 0, right 0, color-stop(0, #f00), color-stop(0.33, #000));
}
Top Left to Bottom Right
button{
background: -moz-linear-gradient(left top, #f00, #000);
background: -webkit-gradient(linear, left top, right bottom, color-stop(0, #f00), color-stop(1, #000));
}
Three Color Gradient (Evenly Distributed)
button{
background: -moz-linear-gradient(left, red, white, blue);
background: -webkit-gradient(linear, left 0, right 0, color-stop(0, red), color-stop(0.5, white), color-stop(1, blue));
}
Three Color Gradient (Unevenly Distributed)
button{
background: -moz-linear-gradient(left, red 0%, white 70%, blue 100%);
background: -webkit-gradient(linear, left 0, right 0, color-stop(0, red), color-stop(0.7, white), color-stop(1, blue));
}
A Crisp Half & Half
button{
background: -moz-linear-gradient(left, white 50%, orange 50%);
background: -webkit-gradient(linear, left 0, right 0, color-stop(0.5, white), color-stop (0.5, orange));
}
Transparency Gradient
button{
background: -moz-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,1));
background: -webkit-gradient(linear, 0 top, 0 bottom, color-stop(0, rgba(0,0,0,0)), color-stop(1, rgba(0,0,0,1)));
}/p>
Example code of all these gradients in action is available on this test page.
Internet Explorer
As I said, Internet Explorer has gradient support as well. In a fashion. Using IE's filters (which aren't actually CSS, but appear in CSS documents), you can do gradients with the following syntax:
button{
filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr="white", EndColorStr="green");
}
That's nice and tidy, isn't it?
No, not really. Fortunately, though, the whole front part is something you can copy/paste without thinking too hard about. It's informing IE that a background gradient is going to be used on the element. Inside the parenthesis is the most important part, which has all of three attributes: GradientType, StartColorStr, EndColorStr. GradientType isn't for something cool like linear versus radial. Rather, it has two values: "0" for vertical gradients, and "1" for horizontal. No angles or clever tricks here.
The StartColorStr and EndColorStr attributes can hold any valid color value. As we're talking about IE here, that's mostly hex codes and color names like "red".
Obviously, the IE version of gradients (which isn't really CSS, I'd like to remind you) is much more limited than Webkit and Firefox's. Of course, it's better than what Opera currently has, which is nothing.
That covers the basic concepts of linear gradients, and how to implement them in Firefox, Webkit and Internet Explorer. That's just the tip of the gradient iceburg, however. In the future I'll talk about radial gradients, gradients with background images, and more!
If you want to pick up more information on using gradients yourself, you can check out the developer resources for Firefox and Webkit.