W3C home > Mailing lists > Public > www-style@w3.org > August 2011

Re: [css3-images] Order of color-stop fixup

From: Leif Arne Storset <lstorset@opera.com>
Date: Mon, 22 Aug 2011 18:35:11 +0200
To: "Tab Atkins, jr." <jackalmage@gmail.com>
Cc: "www-style@w3.org" <www-style@w3.org>
Message-ID: <op.v0mi0xb0tmo5g6@localhost.localdomain>
Tab Atkins Jr. <jackalmage@gmail.com> skreiv Fri, 19 Aug 2011 18:51:11
+0200

> On Fri, Aug 19, 2011 at 5:51 AM, Leif Arne Storset <lstorset@opera.com>  
> wrote:
>> Tab Atkins Jr. <jackalmage@gmail.com> skreiv Thu, 18 Aug 2011 03:46:12
>> +0200
>>> The first problem is illustrated at
>>> <http://www.xanthir.com/etc/gradient-fixup-order.html>.  The page
>>> explains the problem, but I'll summarize it here:
>>>
>>> In the example, we animate the width of the box from 200px to 1000px,
>>> at the same time as we animate the background from linear-gradient(to
>>> right, red 50%, white 100px, blue 100%) to linear-gradient(to right,
>>> red 10%, white 100px, blue 100%).  (In other words, we only change the
>>> position of the red stop.)
>>>
>>> Because the white stop is specified as 100px in both gradients, one
>>> would expect that at all points during the transition the white stop
>>> is either at exactly 100px (when the red stop resolves to less than
>>> 100px) or is at the same position as the red stop (when the red stop
>>> resolve to greater than 100px).
>>>
>>> However, if you do position-fixup early, as the first gradient on the
>>> page does, you get a weird effect where the white stop jumps *ahead*
>>> of the red stop due to the way the linear interpolation works (the
>>> effect is maximized halfway through the transition, when the red stop
>>> is at 180px and the white is at 200px).
>>>
>>> Doing the position-fixup at the last moment instead keeps the white at
>>> a reasonable position the whole time - it's always Math.max(100px,
>>> red.position).
>>
>> Sorry if I'm being dense, but this doesn't make sense to me. I don't get
>> why the white stop should at any point be greater than MAX(red stop,  
>> 100px).
>> Where
>> do you get this from? If I pass the plain gradient, simulating the
>> transitioning effect now moved to level 4, it gives the expected result  
>> in
>> Chromium, Firefox and Opera (see attachment).
>>
>> If I attempt a plain CSS transition in Chromium (also attached), it  
>> gives an
>> effect reminiscent of what you've shown, but only because 'red 10%'  
>> (which
>> applies immediately due to transitioning gradients not yet being  
>> supported)
>> is _less than_ 100px for part of the transition (as opposed to 'white  
>> 100px'
>> being more than 100px, which is what I'm getting from you).
>
> Yes, doing a transition currently, where the gradient immediately
> jumps to the end state, doesn't illustrate anything useful about this.
>  The problem arises when you blend gradients.
>
>
>> Stepping through the code in your script, I see that it's not  
>> positioning
>> the white stop based on the actual position of the red stop:
>>
>> (at 50%:)
>> width       = 600px (50% between 200px and 1000px)
>> red 50%     = 180px (50% between 50% * 600px = 300px and 10% * 600px =
>> 60px)
>> white 100px = 200px (50% between MAX(50% * 600px, 100px) and MAX(10% *
>> 600px, 100px), which works out to 50% between 300px and 100px)
>>
>> It seems that the misplaced white stop comes from interpolating 'red'
>> between 60px and 300px and interpolating 'white' between 100px and 300px
>> (seen from the 50% mark). But the rules don't care about red's
>> hypothetical starting placement at 60px when placing white; they only  
>> care
>> about red's actual current placement at 180px, which is greater than  
>> white's
>> 100px.
>
> Incorrect.  The rules, as written, care completely about red's
> hypothetical position at the two end points, *because* the rules
> currently specify early fix-up.  You *must* first resolve the starting
> gradient into absolute lengths (which pushes the white stop out to
> 300px, when you take into account the box's width at the 50% point),
> and do the same for the ending gradient (white stop isn't pushed, so
> it's at 100px).  *Then*, after doing so, you're allowed to blend them.

Maybe you're getting a bit ahead of yourself - "the rules, as written"
don't really deal with interpolating percentages in gradients or about
mixing percentages and pixels, yet.

But it would make sense to do it that way. I think I wasn't
familiar enough with transitions to see it, but after working through
Shane's example of 'red 20%, white 20px, blue, black 100%' to 'red 0%,
white 20%, blue 40%, black 100%' it makes sense to me: Transitioning
between % and absolute lengths and between implicit and explicit requires
computation.

It might make sense to do something to prevent the color-stop situation
you mentioned when rebooting this thread. [0]

>> Anyway, this strikes me as a strange way of going about it. With the red
>> stop's
>> position being specified both at the start and the end, why don't you  
>> just
>> transition from 50% to 10%?
>
> Because the rules don't allow it.  You're arguing that we should do
> blending before we do fixup, which is exactly what I'm arguing for as
> well.

I guess I am.

>> In any case, there are no implicitly positioned stops here, so swapping  
>> 2
>> and 3 should not make a difference.
>
> It does, because you *do* need to resolve implicit stops before you
> blend (otherwise, you won't know how to blend).  So, if you push fixup
> to after blending, implicit positioning must swap places and occur
> before it.

The point was that the first color stop is the only one without a position
in [1], so step 3 ("If any color-stop still does not have a position")
doesn't come into play. In general, though, I agree that an implicit stop
must be resolved in order to transition to an explicit stop.

> (Alternately, we could mandate two blending rounds, so the
> order would be (1) implicitly position first and last stops, (2) blend
> what you can, (3) fixup, (4) implicitly position the other stops, (5)
> blend the rest.)

Good thinking. I think I may have been imagining a (more naïve) version of
this all along. Your suggestion could be a good compromise.

>> Having said all this, our implementation experience doesn't rule out
>> swapping them, but as an implementor of CSS gradients, keeping the order
>> (2,3) is preferred, as the code appears to be simpler and more  
>> efficient.
>> Furthermore, as a web developer and user of CSS gradients, keeping the  
>> order
>> (2,3) is strongly desired, for the reasons Brian Manthos has explained  
>> quite
>> thoroughly.
>
> I'm neutral on the aesthetics - I think both methods have unique
> useful visual effects.

If I understood Brian correctly he wasn't referring primarily to
aesthetics, but to an even distribution of stops, which in my mind is more
about usability and author expectations than aesthetics. Then again,
author expectations will align to any new spec language, so I'll concede
that point.

0. http://lists.w3.org/Archives/Public/www-style/2011Aug/0485.html
1. http://www.xanthir.com/etc/gradient-fixup-order.html (which is used as
an illustration in
<http://lists.w3.org/Archives/Public/www-style/2011Aug/0485.html>)

-- 
Leif Arne Storset
Core Technology Developer, Opera Software
Oslo, Norway
Received on Monday, 22 August 2011 16:35:12 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:43 GMT