Re: Gradient syntax proposal

On Aug 20, 2009, at 7:01 AM, Tab Atkins Jr. wrote:

> On Thu, Aug 20, 2009 at 12:47 AM, David Perrell<davidp@hpaa.com>  
> wrote:
>> Tab Atkins Jr. wrote:
>> | In the 100px case there is a noticeable difference, though probably
>> | not a *significant* difference - even in the one that preserves the
>> | gradient, it's dropped to a very short, sharp one spanning a mere 5
>> | pixels.  In either case, the 30px green sides, which are presumably
>> | meant to be have padding overlaid on them to keep content out, are
>> | causing a problem all by themselves, independent of the gradient
>> | fades.  You should probably have a min-width placed on the box to
>> | prevent it from ever getting that small in the first place, or  
>> specify
>> | the green sides in % as well.
>>
>> The 5-pixel span is still a soft edge, and the width of the green  
>> is equal on both sides. The one with % measures on the full width  
>> has mismatched sides. A hard transition and mismatched sides could  
>> occur while the wheat-color center is wide enough for text and/or  
>> an image. I made the initial image narrow in order to use two  
>> columns.
>
> Ah, I didn't notice the significance of the mismatched sides on the
> left example.  I assumed you just made a mistake in creating it.
>
> That is produced by a wider issue, though, because the same thing
> would happen with absolute lengths.  Previous color-stops trump later
> color-stops when they fight for position *in general*.  The only way
> around that would be some way of specifying that, past a certain
> point, the later stops should trump earlier stops.
>
> I don't think we need a general solution for this; I believe that in
> virtually all instances this will be about exactly the situation you
> see in your example, where you have a symmetrical gradient that you
> want to keep that way.  I see an opportunity here to let us simplify
> this common case while addressing the problem.
>
> Just like how you can specify a single starting point and it will
> automatically infer the ending point on the opposite side for you
> (allowing you to write "left" instead of the full "left to right"),
> you should be able to specify half of your color-stops and let the
> system infer the other half.  When employing this, you must only
> specify color stops up to 50% - anything larger than that (whether
> purposely, like 65%, or accidentally, like 100px in a 150px box)
> automatically gets dropped back to 50%.  The system will then
> automatically fill in stops for the other half in reverse order, using
> the used values of the original stops and measuring from the end.
>
> I'm not sure what a good syntax for this is, but the first thing that
> comes to mind is this:
>
> linear-gradient(left / green 30px, wheat 20%, mirror)
>
> Which translates roughly into:
>
> linear-gradient(left / green 30px, wheat 20%, wheat 80%, green
> calc(100% - 30px))
>
> But in your 100px example, would instead translate to roughly:
>
> linear-gradient(left / green 30px, wheat 30px, wheat calc(100% -
> 30px), green calc(100% - 30px))
>
> Because the used value of the first wheat color-stop got pushed to
> 30px by the green stop.  This prevents the later asymmetrical conflict
> where the wheat stop sits at 80% and shoves the green stop out of the
> way.
>
> (And yes, Brad, I considered your proposed syntax for this as well.  I
> still find the use of the / there confusing, and think it would be
> *even worse* if it changed the precedence rules as well.  Add in the
> "don't specify anything past 50%" bit, and I think it becomes
> unworkable for this.)
>
> Thoughts?  Better syntax ideas?

Sorry for quoting the entire message, but my brain can't find good  
places to clip, yet today.

Could we allow the designer / user to specify a reference point  
within the gradient? I mean, if you want everything centered, specify  
the gradient line in the middle of the element, then tell CSS that  
everything is offset from the center of the gradient line.

This is just a suggestion, and I can't imagine what a 'good' syntax  
would look like, but imagine if I wanted my gradient centered, I  
might write:

linear-gradient(left 15px to right 15px / 50% / grey -40%, tan, grey  
+40%)

(I know, dumb example.) This would mean the gradient line runs left  
to right in the center of the block, offset 15px from each edge. The  
color offsets are from the 50% point of the gradient line, with grey  
on both left and right edges as 10% of the gradient (50% +/- 40%),  
and the tan in the middle.

Yes, this can be done with calc(), and probably other ways as well.  
But if the user is thinking in terms of centering, would it not be  
more brain-friendly to allow everything to offset from the center?

And, if the user has a menu, say 20em wide on the left edge, he/she  
could specify offsets from the menu edge as:

linear-gradient(left to right / 20em / wheat -20em, red, white, blue)

This would place the wheat on the left, starting at the left border  
(end of the gradient, up to the zero point (now 20 px offset from the  
end), where the red, white, and blue would start.
>
>> On one hand, the gradient on the right does degrade better. On the  
>> other, lengths are relative to the gradient - so why should  
>> percentages be different?
>
> Right.
>
>> Actually, neither color-stop positioning solution is satisfactory  
>> inasmuch as the implicit position of color-stops (subdividing the  
>> span between explicit color stops) doesn't jibe with either. A  
>> default value is normally one of several specifiable options.
>
> Not sure what you're saying here.
>
>> That brings up another possibility: Each color-stop position type  
>> (percent, relative length, pixels) has its own reference span. So  
>> long as all color stops use the same position type, they are all  
>> relative to the length of the gradient. But when a color-stop  
>> position type differs from the previous, the previous stop is the  
>> start position for subsequent stops until the color-stop position  
>> type changes again. If the color-stop position type changes back  
>> to a previous type, the previous type's start reference point is  
>> restored (and it becomes an end reference point if relevant).
>>
>> So, for this gradient:
>>
>> left / blue, red 20%, yellow 2em, green 4em, teal 6px, blue 80%;
>>
>> red->blue gradient is from 0-20% total width. red->yellow is from  
>> 20% to (20%+2em), yellow->green is from (20%+2em) to (20%+4em),  
>> green->teal is from (20%+4em) to (20%+4em+6px), teal->blue is from  
>> (20%+4em+6px) to 80%, and solid blue is from 80%-100%;
>>
>> There, that's pretty simple, right? :-)
>
> Uh, right!  ^_^
>
> While interesting, and perhaps useful, this sort of processing seems
> *way* too complex.  Just use SVG.  ^_^
>
>> | Also, the WG talked not long ago about the introduction of the  
>> max()
>> | and min() functions, which would help in situations like these.   
>> You
>> | could specify the wheat stop as "wheat max(20%, 50px)", ensuring  
>> that
>> | the green->wheat transition remains *at least* 20px wide.   
>> Specifying
>> | the far stop is a bit more complicated, unfortunately - "wheat
>> | min(80%, calc(100% - 50px))" or "wheat calc(100% - max(20%,  
>> 50px))".
>>
>> I seem to recall that suggestion but couldn't find the origin in  
>> the archives. Since it isn't in the Values and Units module, it  
>> will not be of much help.
>
> Last I saw it, it was discussed on a telecon and appeared in the
> minutes.  Here you go:
>
> http://lists.w3.org/Archives/Public/www-style/2009Jul/0176.html
>
> Google is *way* better at searching the archives than the archive
> search is.  Just use a
> site:http://lists.w3.org/Archives/Public/www-style/ specifier on your
> search.
>
> ~TJ
>

Again, sorry for not clipping, but I wanted to capture the idea.  
Maybe I can present it more clearly later, when I actually wake up.

</James>

Received on Thursday, 20 August 2009 14:53:53 UTC