Discussion:
[css-images] cross-fade() interpolation and syntax
(too old to reply)
Dirk Schulze
2013-08-17 13:12:00 UTC
Permalink
Raw Message
Hi,

I have a question to the syntax (1) and interpolation (2) of the cross-fade image function.

1) The currently specified syntax of the CSS Image function cross-fade() is[1]:

cross-fade( <percentage>? <image> [, <image> | <color> ]? )

while WebKit and Blink use:

cross-fade(<image>, <image>, <percentage> | <number>)

WebKit and Blink do not have optional arguments and do not support fallback colors. While fallback colors are certainly a good idea, I think the general syntax currently used in WebKit (and in a previous state of the spec?) looks more logical. Of course this is a matter of opinion, but maybe worth a discussion.

2) The interpolation of cross-fade is specified by:

""If both the starting and ending images are cross-fade()s which differ only by by their <percentage>, they must be interpolated by interpolating their <percentage>. Otherwise, they must be interpolated as generic <image>s.""[2]
typo: s/by by/by/

The question is what "differ only by by their <percentage>" means. Following animation example (WebKit/Blink syntax) with
from:
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 20%), 0%);

and to:
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 80%), 0%);

The second image argument is a cross-fade image function as well, that just differs on the percentage. Are these images considered to be different? So does the implementation need to fallback to generic <image> fading for the whole value? Speaking as an implementer I would be in favor for that, but I am not sure if that is the intention of the specification text. The same for other generated images like linear-gradient and radial-gradient that might have different color offsets. Maybe a little example in the spec could help to clarify that.

Greetings,
Dirk

[1] http://dev.w3.org/csswg/css-images/#funcdef-cross-fade
[2] http://dev.w3.org/csswg/css-images/#interpolating-image-combinations

PS: I really like the paragraph symbol next to the headlines in the spec. I think that is really useful.
Tab Atkins Jr.
2013-08-17 18:01:39 UTC
Permalink
Raw Message
Post by Dirk Schulze
Hi,
I have a question to the syntax (1) and interpolation (2) of the cross-fade image function.
cross-fade( <percentage>? <image> [, <image> | <color> ]? )
cross-fade(<image>, <image>, <percentage> | <number>)
WebKit and Blink do not have optional arguments and do not support fallback colors. While fallback colors are certainly a good idea, I think the general syntax currently used in WebKit (and in a previous state of the spec?) looks more logical. Of course this is a matter of opinion, but maybe worth a discussion.
WebKit and Blink implemented the old grammar - we changed it a while ago.

I think there are good arguments for the current grammar. For one,
the old grammar only allowed fading to a color by using "image(color)"
to generate a solid-color image. That's bad, because the size of the
color-image is the image positioning area, which is probably different
from the size of the source image, which would cause an annoying size
change as you interpolated. I think this is an important use-case so
people can fade to "transparent" to simply "fade out" an image. The
new syntax's ability to take a color directly solves this by not
changing the size of the source image.

The new grammar's defaulting behavior also makes that "fade out"
behavior trivial - you just leave off the second argument. That seems
pretty useful.

Finally, the new grammar is extensible to fading between more than two
images - we can just change the grammar to:

cross-fade( [<percentage>? <image>]# [, <image> | <color> ]? )

and then normalize the percentages if they add up to more than 100%.
Post by Dirk Schulze
""If both the starting and ending images are cross-fade()s which differ only by by their <percentage>, they must be interpolated by interpolating their <percentage>. Otherwise, they must be interpolated as generic <image>s.""[2]
typo: s/by by/by/
The question is what "differ only by by their <percentage>" means. Following animation example (WebKit/Blink syntax) with
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 20%), 0%);
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 80%), 0%);
The second image argument is a cross-fade image function as well, that just differs on the percentage. Are these images considered to be different? So does the implementation need to fallback to generic <image> fading for the whole value? Speaking as an implementer I would be in favor for that, but I am not sure if that is the intention of the specification text. The same for other generated images like linear-gradient and radial-gradient that might have different color offsets. Maybe a little example in the spec could help to clarify that.
I can go either way. As currently written, the spec rules out fancy
interpolation for your example - you'd have to fall back to simple
<image> interpolation.

However, we could change it so that when interpolating two
cross-fade()s, you interpolate the percentage *and* each source image.
This would have identical behavior for the case the spec already
covers, but would also opt your example into fancy interpolation as
well.
Post by Dirk Schulze
PS: I really like the paragraph symbol next to the headlines in the spec. I think that is really useful.
Automatic feature of Bikeshed, yet another inducement to switch
yourself over. ^_^

~TJ
Dirk Schulze
2013-08-17 22:06:12 UTC
Permalink
Raw Message
Post by Tab Atkins Jr.
Post by Dirk Schulze
Hi,
I have a question to the syntax (1) and interpolation (2) of the cross-fade image function.
cross-fade( <percentage>? <image> [, <image> | <color> ]? )
cross-fade(<image>, <image>, <percentage> | <number>)
WebKit and Blink do not have optional arguments and do not support fallback colors. While fallback colors are certainly a good idea, I think the general syntax currently used in WebKit (and in a previous state of the spec?) looks more logical. Of course this is a matter of opinion, but maybe worth a discussion.
WebKit and Blink implemented the old grammar - we changed it a while ago.
I think there are good arguments for the current grammar. For one,
the old grammar only allowed fading to a color by using "image(color)"
to generate a solid-color image. That's bad, because the size of the
color-image is the image positioning area, which is probably different
from the size of the source image, which would cause an annoying size
change as you interpolated. I think this is an important use-case so
people can fade to "transparent" to simply "fade out" an image. The
new syntax's ability to take a color directly solves this by not
changing the size of the source image.
A solution for that could be the syntax of 'fill' and 'stroke'. The current syntax seems just to support interpolation from image to color, but not color to image.

Something like cross-fade(<image> <color>?, <image> <color>?, <percentage> | <number>) would be more powerful.
Post by Tab Atkins Jr.
The new grammar's defaulting behavior also makes that "fade out"
behavior trivial - you just leave off the second argument. That seems
pretty useful.
But what about fade in?
Post by Tab Atkins Jr.
Finally, the new grammar is extensible to fading between more than two
cross-fade( [<percentage>? <image>]# [, <image> | <color> ]? )
Well, you could simple nest them.
Post by Tab Atkins Jr.
and then normalize the percentages if they add up to more than 100%.
Post by Dirk Schulze
""If both the starting and ending images are cross-fade()s which differ only by by their <percentage>, they must be interpolated by interpolating their <percentage>. Otherwise, they must be interpolated as generic <image>s.""[2]
typo: s/by by/by/
The question is what "differ only by by their <percentage>" means. Following animation example (WebKit/Blink syntax) with
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 20%), 0%);
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 80%), 0%);
The second image argument is a cross-fade image function as well, that just differs on the percentage. Are these images considered to be different? So does the implementation need to fallback to generic <image> fading for the whole value? Speaking as an implementer I would be in favor for that, but I am not sure if that is the intention of the specification text. The same for other generated images like linear-gradient and radial-gradient that might have different color offsets. Maybe a little example in the spec could help to clarify that.
I can go either way. As currently written, the spec rules out fancy
interpolation for your example - you'd have to fall back to simple
<image> interpolation.
However, we could change it so that when interpolating two
cross-fade()s, you interpolate the percentage *and* each source image.
This would have identical behavior for the case the spec already
covers, but would also opt your example into fancy interpolation as
well.
I wouldn't fight for the fancy animation :)
Post by Tab Atkins Jr.
Post by Dirk Schulze
PS: I really like the paragraph symbol next to the headlines in the spec. I think that is really useful.
Automatic feature of Bikeshed, yet another inducement to switch
yourself over. ^_^
Always to your service ;)

Greetings,
Dirk
Post by Tab Atkins Jr.
~TJ
Dirk Schulze
2013-08-17 22:32:04 UTC
Permalink
Raw Message
Post by Dirk Schulze
Post by Tab Atkins Jr.
Post by Dirk Schulze
Hi,
I have a question to the syntax (1) and interpolation (2) of the cross-fade image function.
cross-fade( <percentage>? <image> [, <image> | <color> ]? )
cross-fade(<image>, <image>, <percentage> | <number>)
WebKit and Blink do not have optional arguments and do not support fallback colors. While fallback colors are certainly a good idea, I think the general syntax currently used in WebKit (and in a previous state of the spec?) looks more logical. Of course this is a matter of opinion, but maybe worth a discussion.
WebKit and Blink implemented the old grammar - we changed it a while ago.
I think there are good arguments for the current grammar. For one,
the old grammar only allowed fading to a color by using "image(color)"
to generate a solid-color image. That's bad, because the size of the
color-image is the image positioning area, which is probably different
from the size of the source image, which would cause an annoying size
change as you interpolated. I think this is an important use-case so
people can fade to "transparent" to simply "fade out" an image. The
new syntax's ability to take a color directly solves this by not
changing the size of the source image.
A solution for that could be the syntax of 'fill' and 'stroke'. The current syntax seems just to support interpolation from image to color, but not color to image.
Something like cross-fade(<image> <color>?, <image> <color>?, <percentage> | <number>) would be more powerful.
Actually it is either or both. If both are specified, the color is just the fallback.
Post by Dirk Schulze
Post by Tab Atkins Jr.
The new grammar's defaulting behavior also makes that "fade out"
behavior trivial - you just leave off the second argument. That seems
pretty useful.
But what about fade in?
Post by Tab Atkins Jr.
Finally, the new grammar is extensible to fading between more than two
cross-fade( [<percentage>? <image>]# [, <image> | <color> ]? )
Well, you could simple nest them.
Post by Tab Atkins Jr.
and then normalize the percentages if they add up to more than 100%.
Post by Dirk Schulze
""If both the starting and ending images are cross-fade()s which differ only by by their <percentage>, they must be interpolated by interpolating their <percentage>. Otherwise, they must be interpolated as generic <image>s.""[2]
typo: s/by by/by/
The question is what "differ only by by their <percentage>" means. Following animation example (WebKit/Blink syntax) with
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 20%), 0%);
cross-fade(url(1.png), cross-fade(url(1.png), url(2.png), 80%), 0%);
The second image argument is a cross-fade image function as well, that just differs on the percentage. Are these images considered to be different? So does the implementation need to fallback to generic <image> fading for the whole value? Speaking as an implementer I would be in favor for that, but I am not sure if that is the intention of the specification text. The same for other generated images like linear-gradient and radial-gradient that might have different color offsets. Maybe a little example in the spec could help to clarify that.
I can go either way. As currently written, the spec rules out fancy
interpolation for your example - you'd have to fall back to simple
<image> interpolation.
However, we could change it so that when interpolating two
cross-fade()s, you interpolate the percentage *and* each source image.
This would have identical behavior for the case the spec already
covers, but would also opt your example into fancy interpolation as
well.
I wouldn't fight for the fancy animation :)
Post by Tab Atkins Jr.
Post by Dirk Schulze
PS: I really like the paragraph symbol next to the headlines in the spec. I think that is really useful.
Automatic feature of Bikeshed, yet another inducement to switch
yourself over. ^_^
Always to your service ;)
Greetings,
Dirk
Post by Tab Atkins Jr.
~TJ
Tab Atkins Jr.
2013-08-19 18:09:31 UTC
Permalink
Raw Message
Post by Dirk Schulze
Post by Tab Atkins Jr.
I think there are good arguments for the current grammar. For one,
the old grammar only allowed fading to a color by using "image(color)"
to generate a solid-color image. That's bad, because the size of the
color-image is the image positioning area, which is probably different
from the size of the source image, which would cause an annoying size
change as you interpolated. I think this is an important use-case so
people can fade to "transparent" to simply "fade out" an image. The
new syntax's ability to take a color directly solves this by not
changing the size of the source image.
A solution for that could be the syntax of 'fill' and 'stroke'. The current syntax seems just to support interpolation from image to color, but not color to image.
Something like cross-fade(<image> <color>?, <image> <color>?, <percentage> | <number>) would be more powerful.
Note that the color isn't a fallback, it's an alternative way to
specify an "image". But yes, I suppose I'd be okay with extending it
like that. If we did extend cross-fade to accept an arbitrary number
of fading images, we'd have to do this anyway.
Post by Dirk Schulze
Post by Tab Atkins Jr.
The new grammar's defaulting behavior also makes that "fade out"
behavior trivial - you just leave off the second argument. That seems
pretty useful.
But what about fade in?
That's the exact same thing. I didn't mean to imply a direction, just
that it lets you "fade" an image easily, as if you were just animating
opacity on it.
Post by Dirk Schulze
Post by Tab Atkins Jr.
Finally, the new grammar is extensible to fading between more than two
cross-fade( [<percentage>? <image>]# [, <image> | <color> ]? )
Well, you could simple nest them.
Nesting isn't so simple. ^_^ It's ugly and hard to read, and harder
to understand, because the percentages don't work at the same level -
each gets multiplied by the outer percentage.

That is, this:

cross-fade(33% foo, cross-fade(33% bar, baz))

is *not* equal to:

cross-fade(33% foo, 33% bar, baz)

Instead, it's equal to:

cross-fade(33% foo, 17% bar, baz) (approximately)
Post by Dirk Schulze
Post by Tab Atkins Jr.
However, we could change it so that when interpolating two
cross-fade()s, you interpolate the percentage *and* each source image.
This would have identical behavior for the case the spec already
covers, but would also opt your example into fancy interpolation as
well.
I wouldn't fight for the fancy animation :)
Alternative - rather than do nested interpolation, we could add the
variadic cross-fade() right now, and change the interpolation
semantics to just munge all the arguments together, adjusting
percentages as appropriate, cutting the percentages from each of the
inputs in half.

That is, when interpolating from "cross-fade(25% foo, bar)" to
"cross-fade(30% baz, qux)", you interpolation would be:

cross-fade([25% to 0%] foo, [75% to 0%] bar, [0% to 30%] baz, qux)
(qux implicitly goes from [0% to 70%])

This solves the cross-fade() problem (and, somewhat more importantly,
solves the "interrupt an image transition by transitioning to another
image" problem in a nice way, similar to what we can do for lengths
and other things).

~TJ
Lea Verou
2017-06-30 21:21:57 UTC
Permalink
Raw Message
(Response to [1] )

Hi Dirk,

The WG discussed the issue you raised regarding interpolating nested cross-fade() in the Tokyo F2F [2] and resolved to do interpolations recursively on each argument, but mark it at risk.

Is this resolution acceptable to you?

Cheers,
Lea

[1]: https://lists.w3.org/Archives/Public/www-style/2013Aug/0284.html
[2]: https://lists.w3.org/Archives/Public/www-style/2017May/0051.html <https://lists.w3.org/Archives/Public/www-style/2017May/0051.html>

Lea Verou ✿ http://lea.verou.me ✿ @leaverou

Loading...