Re: [css3-images] radial-gradient issue raised by Brad

On Sep 4, 2011, at 11:37 AM, Brad Kemper wrote:

> To even read and understand the WD syntax when seeing it written, an author has to learn the differences of the similar-looking syntax:
> 
> 	• radial-gradient uses a comma instead of a slash to disambiguate between position and size,
> 	• the size values are for a quarter of the image size, not the whole image size,
> 	• the explicit size doesn't give the image implicit dimensions,
> 	• the positioning lengths and keywords apply to the center of the gradient, instead of to the top left 
> 	  (and percentage offsets are even more different), 
> 	• the positioning values move the whole gradient and then clip it to the image dimensions. 

Other things that I found unobvious, leading to a less intuitive learning and authoring experience than when using linear-gradient (which is not to say that they are not sensible choices for this particular syntax, just that they must be learned in order to make sense of radial gradients so that you can write them):

If you want to use an explicit size, you must include the <bg-position> part too (so that the comma will disambiguate).
'closest-corner' and 'farthest-corner' are the same if there is no <bg-position> .
moving the center via <bg-position> does not move it relative to the whole ellipse, it moves the entire ellipse. This means the gradient gets bigger if you have 'cover' or 'farthest-*', and smaller if you have 'contain' or 'closest-*'.
If you specify a  <bg-position> and a <size> keyword, the positioning happens first. This means that the positioning affects the gradient length, then the sizing keyword changes it to something else. If these were done is the opposite order, then only the <size> would affect the gradient length (but it would be harder to get the image filled in common ways). 
Conversely, if you specify a  <bg-position> and an explicit size, the size overrides the effect of positioning on gradient length. 
Even though the spec says "The gradient-ray is anchored at the center of the gradient and extends toward the right", "toward the right" doesn't seem to come into play anywhere, because it is the <size> and <shape> that determine what dimension the percentage stops refer to.
When 'circle' is used, percentage stops refer to the shortest dimension when 'contain'  or 'closest-*' is used, and to the longest dimension when 'cover' or 'farthest-*' is used.
'closest-side' does not equal "shortest dimension" when there is a <bg-position> other than '50% 50%', because the closer you get to one side, the smaller the gradient line gets. This means that in spite of the effort to be able to create any radial gradient, a large use case is unavailable: You cannot create a circle gradient that is centered on one corner with a gradient line that is automatically the width of the image, except when the image width and height are the same. You cannot contain the half width, except with 'farthest-side' non-circles. So for instance, the following is not possible:

	http://www.bradclicks.com/cssplay/impossible-radial-gradient.png

I would have thought that was one of the common use cases. It can be done using backgrounds, of course, but if the idea is to handle all common use cases without using backgrounds, then this looks like a notable failure. For the current syntax to allow it, you would need a modification such that it could be written like this:

background-image: radial-gradient(0 0, 100% circle, yellow, red 99.7%, black 0);

or this for the height circle version:

background-image: radial-gradient(0 0, circle 100%, yellow, red 99.7%, black 0);

You can't use '0 0' with 'closest-side', because you end up with a gradation that is 0 height and 0 width.

But with my simplified syntax, now with position keywords...

radial-gradient(
	[ <side-or-corner>, ]? [circle,]? <color-stop>[, <color-stop>]+
)

...the normal effect would be similar to 'contain', but would not be "closest side", it would be more like "closest side, not including the specified  <side-or-corner>". Thus, if you had this:

background-image: radial-gradient(top left, circle, yellow, red 99.7%, black 0);

...then the 0% horizontal color-stop would be on the left, and the 100% on the right. Likewise the  0% vertical color-stop would be on the top, and the 100% on the bottom. 

With this new version of the syntax, you would also be able to create most (if not all, I'm not sure) of the CSS3 Patterns in Lea Verou's gallery. AND, you would be able to easy figure out what length a percentage-based color-stop translated to. It would ALWAYS be a percent of the image height and width for all <side-or-corner> keywords, or half that for centered gradients. 

You would not need to multiply by .715 or 1.42 or whatever it is when 'cover' is in play, in order to convert between color stop percentages and actual lengths. And you would not need to figure some proportion based on the absolute value of the <bg-position> componants, or determine if you instead needed to look at <size> for the gradient length. It would be simple, percentages based on image size always, and you'd still have all the power for the common use cases, and even many of the uncommon use cases. And you could still draw little vector-like pictures using hard-edged "gradients".

If you wanted a radial gradient color stop that went beyond the sides, you'd just use a color stop that was more than 100% (142% to get to the corners). It's easy, and keeps the model and the calculations easy. You'd always know where the 50% or 100% color stops would be in relation to the image width and height, which seems much more useful than knowing where they are in relation to the corners.

Received on Tuesday, 11 October 2011 17:09:56 UTC