[css3-images] Simplifying radial gradients

Brad recently sent an email with feedback on radial gradients, arguing
for a significant simplification.  Below I quote only his conclusions;
his full email can be found at
<http://lists.w3.org/Archives/Public/www-style/2011Sep/0019.html>

On Sun, Sep 4, 2011 at 11:37 AM, Brad Kemper <brad.kemper@gmail.com> wrote:
> • Explicit sizing within the image offers no advantages over 'background-size', aside from the entirely theoretical and unlikely or rare use outside of backgrounds.
> • 'farther-side' is only useful when there is a offset center within the image. But such offsets within the image are not necessary, because the entire image can be positioned within the background positioning area.
> • 'closest-corner' is not useful.
> • Limiting the implicit sizing keywords to 'contain' and 'cover' would be more than enough power to include, and would simplify the understandability of the syntax. Since 'cover' is the same as ('contain' x 142%), the syntax can be simplified even more, and eliminates multiple way of doing the same thing. This simplification would be a great benefit to authors and learners, with little to no downside.
> • Letting all radial gradients be 'contain' has a slight expressive advantage (for when you want a hard edge color stop to just touch the sides) over letting them all be 'cover', without giving up any of the power to create gradients that do cover.
> • Letting the 'circle' keyword create an implicit aspect ratio for the image will benefit authors positioning a round gradient that has width or height that is based on a percentage of the background positioning area.
> • Adopting a more limited approach now for CSS3 images does not prevent us from adding back in more controls for CSS4 images if there turns out to be a greater demand for it (which I still consider unlikely).
> • Having a syntax that is nothing but color stops and an optional "circle" keyword is so simple that anyone can quickly and easily learn it, without having to understand complex interrelationships of more complex syntax. Given that these type of images will most often be used almost exclusively in backgrounds, it will be sufficient to use existing background properties for position and size.
> • Any radial gradient needs beyond those can be handled with this simpler syntax are more appropriate for SVG. We already have this distinction for linear gradients, to great effect, and we should carry the same guidance into designing the radial-gradient syntax.
> • The need for radial gradients starts out being small compared to the need for linear gradients. The need to offset the gradient within the image or size the gradient within the image for gradients appearing in non-backgrounds, or in places where they cannot be sized or positioned by other means (mostly this is list markers and border images) extremely minor, and we should not be adding complexity to the syntax for just those rare and limited cases.

His proposal is to simplify the syntax to:

radial-gradient( [circle,]? <color-stop># );

With this, gradients would automatically be centered and use "contain"
sizing.  The 'circle' keyword would switch between a circular and
elliptical gradient.

Overall, I'm sympathetic to his arguments.  Linear gradients have been
simplified  significantly due to feedback.  Radial gradients have
received much less feedback, and so probably have received less
pressure to simplify.  As well, it is true that most of the complexity
doesn't appear to be needed for the non-background uses of radial
gradients - they'd generally be okay with a centered box-filling
gradient.  Much of the complexity isn't strictly needed for background
uses, either - most of them can be addressed by the
background-position/size.

One of the reasons for the complexity was specifically to address
Transitions - Simon argued that we should always be able to represent
the intermediate forms (so that, for example, we can return it if
getComputedStyle() is called in the middle of a transition).  I agree
with this, but I've also come to believe it's less of an issue.  The
best-looking linear-gradient transitions can, barely, be expressed
within the linear-gradient syntax, but it would be probably be clearer
to explicitly do something like "transition(<gradient 1>, <gradient
2>, <percentage>)" (basically, the cross-fade() function, just
generalized for all transitions).  Something like transition() would
probably be required for other types of transitions that we need to
allow, like "height:200px" to "height:auto".  Once transition()
appears, we could use it for representing the intermediate forms of
radial gradients as well.

I disagree with Brad's assertion that it's acceptable to only use
"contain" sizing and require authors to multiply their color-stop
positions by sqrt(2) to achieve "cover" sizing.  The fact that this
works requires some trigonometry work to figure out, and is not
generally known.  At the very least, I'd argue that "cover" *must* be
included.

An additional downside of simplifying as Brad suggests is that it
becomes harder to both explicitly size a gradient and make the
gradient cover the entire element.  This is useful for, for example,
"spotlight" effects.  This can be solved by making the gradient
extra-large (say, 200% 200%), so the image always covers the full
area.  This would also be solved by "background-position:extend",
which may show up in B&B4.

Another downside is performance-related.  To position a gradient in
the upper-left corner, for example, you'd have to do:

background-image: radial-gradient(white, black);
background-size: 200%;
background-position: 100% 100%;

This produces an image four times as large as the element, even though
you'll only be using a quarter of that, which is somewhat wasteful of
system resources.  I'm not sure how big of a deal this is, though.


So, with this taken into account, a possible simplification is the following:

radial-gradient(
  [ circle || [cover | contain], ]
  <color-stop>#
)

~TJ

Received on Tuesday, 20 September 2011 01:25:01 UTC