We recently had a thread about gradients that exploded in size pretty
quickly. This email is intended to recenter the conversation and
solve the problem (if indeed there is a problem).
The message that started the thread was
<http://lists.w3.org/Archives/Public/www-style/2011Jun/0175.html>,
from Brian Mantheos. In it, he stated that he felt the directional
keywords in linear gradients were opposite what they should be.
To quickly summarize the issue, when I'm determining how to specify a
linear gradient using an angle, I do so by thinking about a compass
rose with degrees labelled around it, like:
315deg 0deg 45deg
^
|
270deg <---+---> 90deg
|
v
225deg 180deg 135deg
In other words, I determine what angle to write down based on where on
the compass I want the gradient to go towards. If I want it to go up
I look at the top and see 0deg, if I want it to go to the left I look
to the left and see 270deg, etc.. I believe Brian's mental model
matches mine, and I suspect most authors do approximately this as
well.
Similarly, I have a compass rose-like model of the directional keywords:
top-left top top-right
^
|
left <---+---> right
|
v
bottom-left bottom bottom-right
However, if I try to use this mental model in the same way as I did
the angle-rose, I get bad results with the current WD definition
(don't look at the ED - it's got different text). If I want a
gradient to go up, I look up and see 'top', but I have to write
'bottom'. If I want it to go left, I look to the left and see 'left',
but I have to write 'right'.
This discrepancy is due to historical issues - originally, linear
gradients were defined with start and end points. Later, angles were
added, the end-point was dropped, and the start-point was simplified
to only refer to the 8 points you can specify with keywords. So, when
you're using keywords, you are specifying where the gradient should
start, because that argument originally specified the starting point
of the gradient-line explicitly.
The simplifications that have occurred over time to the gradient
syntax, though, means that it's no longer clear from context that it's
supposed to be a starting point. I believe that, given the mental
model mismatch outlined above, it makes more sense now to have the
keywords indicate the side/corner the gradient is going towards, to
match the way angles are understood.
There are some alternate approaches to this problem that solve the
discrepancy in different ways.
1. Drop the keywords entirely, and just use angles. If you want a
corner-to-corner gradient, just estimate what angle it will be. It's
relatively difficult to tell apart most gradients that differ by only
10 or 15 degrees, which seems like a reasonable accuracy to ask
authors to estimate within. (The spec has an example distinguishing a
45deg gradient from a corner-to-corner gradient in a box with a 2:1
width:height ratio, which is a difference of about 20deg. The two
gradients look roughly the same.)
2. Drop the keywords entirely, and instead using an optional
"as-square" keyword alongside angles. This would first resolve the
angle as normal against a square canvas, then scale the canvas to its
proper size, scaling the relative positions of the gradient endpoints
as well. This way, a corner-to-corner gradient can be achieved by
specifying "45deg as-square" - 45deg produces a corner-to-corner
gradient if the canvas is square, and then the endpoints are held
steady in the corners when the canvas is scaled to its proper size.
3. Drop the keywords, and add an optional "snap" keyword alongside
angles. This would change the used value of the gradient to make the
angle point exactly at the corner in the same quadrant as the angle.
For example, "45deg snap" would always point toward the top-right
corner, no matter what the box dimensions are. So would "20deg snap"
or "89deg snap". Integer multiples of 90deg would be left unchanged.
And then, just to give us numbers for everything:
4. Keep the keywords how they are (current WD wording).
5. Reverse the meaning of the keywords (current ED wording).
My preferences are, in order, 3 > 1 > 5 > 4 > 2.
#1 is simple and mostly okay. It doesn't solve the use-case of
drawing exact corner-to-corner gradients well, which I think is a
reasonable use-case. However, in most cases it should be close
enough.
I don't like #2, because it introduces an extra level of abstraction,
and in a new form than anything else. You're resolving the gradient
angle at one size, and then color-stop positions at another size.
I think #3 works well. It solves the problem of things being
unintuitive, and does so in a way that people are also used to. All
graphics programs have some notion of "snapping" angles to a
particular set of privileged ones. They differ in which angles they
privilege, and we're no different here. (Most of them snap to round
degrees and let you do corner-to-corner manually, because that matches
what's hard and easy in drawing programs. The two tasks have opposite
difficulty in CSS, so we snap to corners and let you do degrees
manually.) The big downside is that this introduces lots of "rounding
matters" behavior, which I otherwise prefer to avoid. That's part of
its essential nature, though.
I no longer like #4, because I've convinced myself that the mental
model mismatch is a problem that needs to be solved somehow.
I'm okay with #5, because it fixes my expectations. However, I'm not
very fond of keeping the same keywords and just reversing their
meaning - that sounds like a recipe for confusion. On the other hand,
the current keywords are still the best that I've been able to come up
with.
An additional benefit of 1-3 is that it would remove the transition
problem that the keywords have (going from top->right is the same as
0deg->90deg, but from left->top is 270deg->0deg, a 3/4turn CCW
rotation). I've manually patched the problem in the current ED, but
avoiding it in the first place would be nice.
So, thoughts?
~TJ