Surfin' Safari

Introducing CSS Gradients

Posted by Dave Hyatt on Monday, April 14th, 2008 at 12:39 pm

WebKit now supports gradients specified in CSS. There are two types of gradients: linear gradients and radial gradients.

The syntax is as follows:

-webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*)

The type of a gradient is either linear or radial.

A point is a pair of space-separated values. The syntax supports numbers, percentages or the keywords top, bottom, left and right for point values.

A radius is a number and may only be specified when the gradient type is radial.

A stop is a function, color-stop, that takes two arguments, the stop value (either a percentage or a number between 0 and 1.0), and a color (any valid CSS color). In addition the shorthand functions from and to are supported. These functions only require a color argument and are equivalent to color-stop(0, ...) and color-stop(1.0, …) respectively.

Paraphrasing the HTML5 spec and adjusting the language slightly to not be canvas-specific:

“The color of the gradient at each stop is the color specified for that stop. Between each such stop, the colors and the alpha component must be linearly interpolated over the RGBA space without premultiplying the alpha value to find the color to use at that offset. Before the first stop, the color must be the color of the first stop. After the last stop, the color must be the color of the last stop. When there are no stops, the gradient is transparent black.

If multiple stops are added at the same offset on a gradient, they must be placed in the order added, with the first one closest to the start of the gradient, and each subsequent one infinitesimally further along towards the end point (in effect causing all but the first and last stop added at each point to be ignored).”

The points of a linear gradient specify a line. Linear gradients must be rendered such that at and before the starting point the color at offset 0 is used, that at and after the ending point the color at offset 1 is used, and that all points on a line perpendicular to the line that crosses the start and end points have the color at the point where those two lines cross (with the colors coming from the interpolation described above).

If x0 = x1 and y0 = y1, then the linear gradient must paint nothing.

For a radial gradient, the first two arguments represent a start circle with origin (x0, y0) and radius r0, and the next two arguments represent an end circle with origin (x1, y1) and radius r1.

Radial gradients must be rendered by following these steps:

If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing. Abort these steps.

Let x(ω) = (x1-x0)ω + x0

Let y(ω) = (y1-y0)ω + y0

Let r(ω) = (r1-r0)ω + r0

Let the color at ω be the color of the gradient at offset 0.0 for all values of ω less than 0.0, the color at offset 1.0 for all values of ω greater than 1.0, and the color at the given offset for values of ω in the range 0.0 ≤ ω ≤ 1.0

For all values of ω where r(ω) > 0, starting with the value of ω nearest to positive infinity and ending with the value of ω nearest to negative infinity, draw the circumference of the circle with radius r(ω) at position (x(ω), y(ω)), with the color at ω, but only painting on the parts of the surface that have not yet been painted on by earlier circles in this step for this rendering of the gradient.

This effectively creates a cone, touched by the two circles defined in the creation of the gradient, with the part of the cone before the start circle (0.0) using the color of the first offset, the part of the cone after the end circle (1.0) using the color of the last offset, and areas outside the cone untouched by the gradient (transparent black).”

So what exactly is a gradient in CSS? It is an image, usable anywhere that image URLs were used before. That’s right… anywhere. :)

You can use gradients in the following places:

background-image
border-image
list-style-image
content property

Gradients as Backgrounds

When specifying a gradient as a background, the gradient becomes a background tile. If no size is specified, then the gradient will size to the box specified by the background-origin CSS3 property. This value defaults to padding, so you the gradient will be as large as the padding-box. This is equivalent to a specified background-size of 100% in both directions.

If you want to achieve effects like tiling of a vertical gradient using a narrow strip, you should specify background-size to give the gradient tile an explicit size.

Gradients used as backgrounds will respect full page zoom, acquiring sharper resolution as the page is zoomed in.

Background Gradients Example

Border Image Gradients

Gradients can be used as border images. The most sensible use for them is specifying only horizontal or only vertical borders (and splitting the gradients up between the top and bottom or left and right borders).

The size of the gradient image is always the size of the border box.

Border Image Gradient Example

List Bullet Gradients

Gradients can be specified as list bullets. One problem with list bullet gradients is that there is currently no way in WebKit to specify the size of the marker box. Therefore the size of the image cannot be specified. WebKit has therefore chosen a default size based off the current font size of the list item.

List Item Gradients Example

Generated Content Gradients

Gradients can be used inside the content property. The image will fill the available width and height of its containing block. Therefore when using gradients inside ::before and ::after content with a specified size, it is important to set the display type to block or inline-block.

Gradients can also be used to do image replacement, so can be used with the img element in HTML or to replace the contents of other elements like spans and divs.

Generated Content Gradients Example

Final Notes

WebKit now supports a generic architecture for generated images, making it easy to add new generator effects to CSS in the future (lenticular halos, checkerboards, starbursts, etc.). The rules for sizing of these generated images will match whatever is decided for SVG content with no intrinsic size (the two are sharing the same rules right now).

We encourage you to try gradients out and file bugs if you see any unexpected or weird behavior. They will degrade safely in other browsers as long as you use multiple declarations (e.g., specify the image in one declaration and the gradient in a following declaration).

32 Responses to “Introducing CSS Gradients”

  1. jeffr Says:

    This is awesome! I really like the way webkit is developing and hope other browsers take note. It’s incredible how far ahead webkit is in the browser race.

  2. Jubal Says:

    Gotta wait for the next build to try out the generated gradient contents example. The rest are impressive.

    Well done!

  3. Matt Lilek Says:

    This is so sexylicious, hyatt++

  4. POWRSURG01 Says:

    I have always wondered why this isn’t a part of CSS. It makes so much logical sense.

    I just wish that we could use this any time in the next 7 years. :(

  5. gavza Says:

    If I zoom in on the background gradients example, the box with the gradient stays the same size, rather than zooming in and acquiring sharper resolution as the blog post suggests. In fact, none of the gradient containing elements in any of the examples get bigger when zooming in. I’m using r31878. Should I file a bug, or is this expected behavior?

  6. xhva Says:

    You’re going to be on a lot of designers’ Christmas card lists this year Hyatt. <3 !

    This is a feature I’ve always wanted in CSS. Thankyou.

    Was this discussed at the CSSWG meet a few weeks ago? Daniel Glazman’s reaction to the webkit bug hints at prior knowledge :)

  7. Ahruman Says:

    @gavza: you’ll need to enable full-page zooming (the secret handshake was mentioned a few posts back).

    With full-page zooming enabled, the Border Image Gradients falls apart when it’s scaled in r31878 (current nightly).

  8. xhva Says:

    Gavza: The box dimensions are specified in px and Safari does text zoom atm, so they don’t get bigger. If you save the example and change the unit to em they’ll resize. The radial examples won’t enlarge without changes because of the way the gradients are specified in the source, but the second (linear) example works fine.

  9. eAi Says:

    Great! Just what I asked for a few weeks back! How about using it on the gradients on this page? The background should be easy, but can you do the top title bar and side nav bars?

  10. gavza Says:

    doh – my bad. I had enabled full page zooming previously, but just got a new machine, and forgotten it wasn’t enabled. Indeed, it works great!

  11. xhva Says:

    A couple of questions:
    – Any chance of allowing “transparent” as a stop colour?
    – Is radius meant to accept a unit? I can use percentages for points (so gradients position correctly on differently-sized containers) but supplying a unit value for radius kills the declaration.

    I made a quick testcase for two other issues: http://xhva.net/webkit_r31878_gradient_radial.html
    – A single pixel isn’t drawn in the centre of gradients with some radius sizes
    – Not sure if it’s intentional, but the end colour bleeds outside the radius boundary.

    Hope this helps! :)

  12. Matt Lilek Says:

    @eAi: Sure you can. The title bar is easy, the nav bar is a little bit harder and a bit hackish. I’ve done some quick examples, which are available at . It’s not pixel perfect compared to the standard webkit.org, but for only using one image on the entire page (the compass in a box), it’s not bad.

  13. Matt Lilek Says:

    Gah, WordPress at my link, hopefully this will work: http://mattlilek.com/webkit-cssgradient.html

  14. Pingback from log » CSS Gradients:

    [...] text & box shadows, hsla/rgba support and multiple backgrounds) is vendor-prefixed support for CSS Gradients. I’m encouraged knowing that Hyatt is on the CSSWG with a bunch of interesting specs proposed [...]

  15. Ankur Says:

    Nice work. Just yesterday I hacked together CSS gradients using drop shadows – guess I’ll be changing it now.

  16. rhuantavan Says:

    This is great news, now let’s just cross fingers so that other browsers start supporting these fabulous features.

  17. Pingback from Noscope | Journal | Some Ad-Hoc Quick Thoughts On WebKits Addition Of CSS Gradients:

    [...] the browser engine that powers Safari, now supports CSS gradients. For the unenlightened, Safari also supports drop shadows and rounded corners. If you’ve ever [...]

  18. cgpitt@gmail.com Says:

    Well done guys. Any idea when these changes will be absorbed into the AIR runtime?

  19. Pingback from Webkit provides implementation of CSS-based gradients - CSS3 . Info:

    [...] CSS Gradients in Webkit [...]

  20. asbjornu Says:

    Although I haven’t read the CSS3 specification on the matter, I reckon this implementation is in line with it. However, wouldn’t it be more natural to have the gradient function as a value of ‘color’ properties and not ‘image’? After all, you’re specifying colors, not images. So instead of ‘background-image’ you’d have it on ‘background-color’, ‘border-color’ instead of ‘border-image’ and ‘list-style-color’ (had it existed) instead of ‘list-style-image’.

  21. Stifu Says:

    I agree with asbjornu. Besides, making it usable through background-color would let us have a background-image on top of the gradient, while having a background-color along with a gradient doesn’t make sense.

  22. marc nothrop Says:

    I tend to agree with asbjornu; CSS gradients would certainly be useful as a Color property, an obvious example being the combination of alpha-blended images on a gradient backgrounds, and switching the gradient/opacity on hover, for navigation, buttons etc.

    OTOH there are interesting opportunities for gradients and Image-Repeat, and IMHO it’s entirely valid to have both; just as vector shapes can have gradient fills (background-color as appropriate) and gradient strokes (border-color).

    Of course, there’d have to be a bit of thinking about the implications of Border-Style, e.g. how should a gradient apply to Dashed lines?

    Finally gradients as Color properties would enable gradients as Text fill, and likewise on Text-Stroke, which could certainly be useful.

  23. rbiggs Says:

    asbjornu and Stifu, you can use it as a definition of background, however, it appears you can also attach an image as a background. On a different note, I guess the attachment of CSS gradients to the CSS image properties explains why I wasn’t able to animate them using transition, etc. Hmmm… I was looking forward to that. Maybe Hyatt and company could rethink how they’ve implemented it and refactor it as belong to the color properties, thus allowing CSS gradients to be animatable. That would give Flash and Silverlight a run for their money.

  24. Pingback from Dylan Schiemann » Blog Archive » future of svg, revisited:

    [...] an interesting approach of leveraging key SVG stylistics features and exposing them through CSS: CSS gradients, CSS transforms, and CSS animations. What’s really interesting is that some of the best [...]

  25. Stifu Says:

    rbiggs: I was thinking they may have done it that way for backward compatibility reasons. Like, you can set a background image followed by a gradient declaration, so browsers that don’t support gradients still fall back on the background image (as explained at the end of the article). So that’d ease up the transition somehow. But that’s still wrong and illogical, IMO.

  26. Dave Hyatt Says:

    The problem with using gradients as colors is that you then have no control over the placement of the gradient, the size of the gradient, etc. For example, background-color just fills the entire space. If gradients were done as colors, you’d have no way to control the gradient tile’s size, tiling rules, origin, etc.

  27. Steven Fisher Says:

    I just downloaded the latest nightly, and I’m still not seeing border or bullet gradients. This is supposed to work now, right?

  28. lelya Says:

    Hi! Anyone can show result’s screenshots?
    Tnx!

  29. memil Says:

    awesome, although I have problems with non standard extensions to html, css and javascript. back in the old bad days the browser venders used this to try to shut out the other browsers (some still do) and I really hope we won’t see that again

  30. David Smith Says:

    memil: Apple’s new web features are almost always (always? not sure if there’s any examples of ones that haven’t been, except for gradients which are still a work in progress) submitted for consideration as standards. That’s why the vendor prefix exists in CSS (-webkit-propname ).

  31. marc nothrop Says:

    @Dave Hyatt:

    “The problem with using gradients as colors is that you then have no control over the placement of the gradient, the size of the gradient, etc. For example, background-color just fills the entire space.”

    That’s true, but there are circumstances where that’s exactly what the designer might want.

    Of course I realise that my example (nav/button elements via gradient background-color and an overlaid image) could also be achieved via multiple background images, but that doesn’t reduce the value of a background image/colour combination.

    “If gradients were done as colors, you’d have no way to control the gradient tile’s size, tiling rules, origin, etc.”

    True, so if that matters you’d use gradients via Image, whereas if you want a gradient fill on Text/Text-Stroke, or a Border use gradients via Color.

    IMHO it’s logical and defensible to think of gradients as both an Image and Color property.

  32. Black Bloke Says:

    I asked in the comments of the last post, but by that time everyone had already moved on. Hopefully I can get some guidance this time:

    “Will SVG images ever be clickable and draggable in Safari/Webkit? I mean in the same way that almost all other images file types are: e.g. JPG, GIF, PNG, etc.

    Or perhaps the ability is there already and I’ve only missed it?”