CSS gradient syntax: comparison of Mozilla and WebKit (Part 2)

Warning This article was written over six months ago, and may contain outdated information.

Update: I wrote this article in 2009. In early 2011 WebKit decided to change their syntax to match that used in Firefox (and the W3C specification). The syntax contained in these articles will be maintained for reasons of backwards-compatibility, but you should use the new syntax for the future. I’ve written a post about the new radial gradient syntax.

In the first part of this post I gave a potted history of the differing syntaxes, and provided an overview of how that affected linear gradients. In this second part I’m going to look at radial gradients.

Here the syntaxes diverge slightly more, with WebKit requiring more values than Mozilla; while that adds some flexibility, it also increases the complexity.

I’ll be using the same page of examples, which you’ll need to view in Safari / Chrome (or other WebKit derivative) or Firefox 3.6 (beta 3+):

CSS Gradients comparison: Mozilla & WebKit

Radial gradients

As with linear gradients, the key differentiation between the Mozilla syntax and the WebKit syntax is that the latter requires a start and end point, whereas the former is constrained by the bounding box.

You can see in this first example (Radial 1) that the Mozilla syntax is much shorter when making a simple two-colour radial gradient:

-moz-radial-gradient(green, yellow);
-webkit-gradient(radial, center center, 0, center center, 70.5, from(green), to(yellow));

In Mozilla’s case I set only start and end color-stops; for WebKit I must specify a position (50% 50%) and radius (0 — I’ll explain that later) for the start point, and a position (50% 50%) and radius (70.5) for the end point, as well as the color-stops.

As far as I can see the radius value has to be a value in pixels, so in order for the end radius to be the diagonal of the square (where Mozilla defaults to) you need to use the calculation (side)(sqrt(2)) — or, do what I did and use this online calculator.

In the next example (Radial 2) I’ve offset the center of the gradient and set it to end at the furthest edge of the containing box:

-moz-radial-gradient(40% 40%, farthest-side, green, yellow);
-webkit-gradient(radial, 40% 40%, 0, 40% 40%, 60, from(green), to(yellow));

And then used the same center offset but constrained the radius to the distance of the nearest wall (Radial 3):

-moz-radial-gradient(40% 40%, closest-side, green, yellow);
-webkit-gradient(radial, 40% 40%, 0, 40% 40%, 40, from(green), to(yellow));

As you can see, Mozilla takes a series of constants using natural language — farthest-side, closest-side, contain, etc — to set the limits of the gradient, where WebKit accepts only pixel values. The advantage to the former approach is that the syntax is simpler and no calculations are required; the disadvantage is that if you want to create a radial gradient that is smaller than the limits of the containing box, you have to combine it with the background-size property.

Next (Radial 4) I’ve set the center of the gradient to the top-right corner, using three colours equally distributed; here’s where you can start to see the WebKit syntax start to become really unwieldy:

-moz-radial-gradient(right top, green, yellow, blue);
-webkit-gradient(radial, right top, 0, right top, 141, from(green), color-stop(50%, yellow), to(blue));

With WebKit I again have to specify start and end points (with radii), and also specify the stop position of the middle colour. Both outcomes are the same, but the Mozilla syntax is significantly easier.

One aspect of WebKit’s syntax which allows for more flexibility in a gradient is the start point and end point; by providing two separate values you can set the start gradient at a different point to the end gradient, as well as providing different radius values, allowing for effects that Mozilla can’t easily replicate (Radial 5):

-moz-radial-gradient(60% 60%,circle contain,yellow,green 75%,rgba(255,255,255,0));
-webkit-gradient(radial,45% 45%,5,60% 60%,40,from(yellow),color-stop(75%, green),to(rgba(255,255,255,0)));

You can see how that is rendered here (Mozilla on the left, WebKit on the right):

Comparison of CSS gradients

Achieving the same effect is only possible in Mozilla by using multiple values on the background-image property, along with background-size (Update: This isn’t necessary; see Tab Atkins Jr’s comment, below).

Conclusions

While the (original) WebKit syntax does allow for a few effects that the simpler Mozilla implementation can’t easily copy, I think these are really edge cases and the simplicity of the newer syntax is more than ample compensation. It seems the CSS WG agree, which is why the simple syntax is to become an official proposal; I hope the WebKit team accept the proposal and implement it soon.

It was suggested that I also compare these with Internet Explorer’s Gradient filter, but that’s a browser-specific implementation that has no chance of becoming a standard, so I didn’t feel it was suitable for this article; perhaps in a future extension.

Update: Just after I finished this article, Mozilla Hacks published an in-depth look at the new syntax.

17 comments on
“CSS gradient syntax: comparison of Mozilla and WebKit (Part 2)”

  1. You don’t need to use background-size to get a gradient of a different size in the current syntax. Just set your color-stops appropriately, especially the last one. If your last color stop is at 50%, then the gradient will be half the size of normal.

    And yeah, I sort of like the skew effect you can get with the original Webkit syntax, but it turns out to complicate the syntax too much. I valued the ability to do gradients that depended on the box size more than I valued the ability to do a skew like that. The original drafts of the syntax did have that ability, it just gradually dropped out as we hacked on it in the mailing list.

  2. Thanks for correcting me, Tab; I’ve updated the post to reflect your feedback. Good work on simplifying the syntax, by the way.

  3. Social comments and analytics for this post…

    This post was mentioned on Twitter by angelus12: RT @stopsatgreen CSS gradient syntax: comparison of Mozilla and WebKit (Part 2) | Broken Links http://bit.ly/5jHxQt

  4. Hi Peter,

    Unrelated to the articles (which were very well explained by the way), but when I first tried accessing your site in Webkit nightly on a Mac, it crashed my browser after warning me about downloading Grablau Sans. Each time I tried to restart the browser it would crash again after trying to load the page. So I switched to Safari and got the same problem.

  5. Hello Peter,

    Well done on these two articles. Now time to have fun with it.

  6. @ John — Thanks for letting me know. I can’t replicate the problem myself, and other Safari users are visiting the site with no problems. What version are you using? I’ll try to replicate the problem myself.

    @ Jason — Thanks very much. Let me know if you cook up any cool stuff.

  7. Tab,

    Please explain how the Webkit syntax does not have “the ability to do gradients that depended on the box size.” It certain seems to have that ability to me.

  8. Tab, I see now, sorry. In Part 1 it is made clear all the cool different box-model-aware sizing options in the new syntax. Very cool.

  9. @John Faulds: After investigating this further, seems like Safari doesn’t like the font-weight property inside @font-face; I need to investigate this a little more.

  10. […] CSS gradient syntax: comparison of Mozilla and WebKit (Part 2) […]

  11. […] There are two great articles on this topic, delver deeper into the syntax differences: CSS gradient syntax: comparison of Mozilla and WebKit and CSS gradient syntax: comparison of Mozilla and WebKit (Part 2). […]

  12. Hey these two parts are awesome.
    I really like it and read it more than 5 times to get everything in my head.
    I totally agree with you conclusion, but there is one problem I can´t solve at the moment.
    You said, with a little help of TAB that firefox is able to show the right result with another gradient.
    But i am unable to put 2 gradients in the background-image property.
    How would it look like!

    Thx!

  13. Hi, thanks for your kind comments. You can use multiple background images in Firefox 3.6; you just need to use comma-separated values for the property:

    background-image: gradient, gradient;

    Just make sure your copy of Firefox is updated to 3.6.

  14. While I certainlythink that Mozillas approach is easier, there’s one thing that Webkit can do but I havn’t seen or figured out to do in FireFox, and that’s “compound” gradients. Can I have multiple gradients layered upon each other, like the WebKit example imaged here (the top top): http://i2.sitepoint.com/g/nl/tt/cssgradients.jpg

    In WebKit this is done this way (where three gradients are layered on top of each other):
    background: –webkit-gradient(properties 1), –webkit-gradient(properties 2), –webkit-gradient(properties 3);

    Is there a way to do this in Firefox?

    Henrik Wannheden [May 25th, 2010, 11:30 pm]

  15. You can certainly do that in Mozilla browsers:

    background: { –moz-radial-gradient(20% 50%,circle,white,black 95%,transparent), –moz-radial-gradient(50% 20%,circle,black,white 95%,transparent), –moz-radial-gradient(10% 10%,circle,white,black 95%,transparent); }

    The trick, as you can see, is to remember to set the last colour of each gradient to ‘transparent’; if you don’t, the last set colour will fill the rest of the box and other gradients will be hidden.

  16. […] (reference: http://www.broken-links.com) […]

  17. This is one object where the W3C team has never really addressed the issue of gradient colors. It would be great if they would develop a standard as it would remove a ‘lot’ of graphic work, improve page load times and be more in line with the HTML5-CSS3 standards. Guess we’ll have to wait. :(