You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Allow interpolation between both viewport and element breakpoints.
The problems with clamp(), min(), and max() is that you can only interpolate length values on a single property between two points. You may want to interpolate rulesets across multiple breakpoints. You may also want to interpolate things like variable font settings, color, etc. Additionally it would be nice to be able to ease how breakpoints are interpolated as rates at which things scale across different screen or element sizes can often be variable.
Yeah, this would be real useful for something like "intrinsic typography" - but I can imagine other use-cases as well. It's interesting to think about media/container "breakpoints" as keyframes in an animation, which we can then interpolate (with easing).
My immediate association is scroll-timeline. I wonder if there would be a way to adapt something similar to get, basically, a container-timeline.
@mirisuzanne and I put together this proposal for defining and using query-linked timelines as part of rethinking various features for animation timelines and interpolation and how to fit them all together.
Query-linked Timelines
Query-linked interpolation uses a set of keyframes (minimally, two) to interpolate values along an easing curve based on the value of a query (such as a media query or container query). The timeline is therefore defined by the value of the query, and can be referenced by an interpolation function in individual property declarations.
Defining the Query Timeline
The @timeline rule defines a named timeline. It can be expanded later to define other types of timelines, but here we're defining only two types: media query timelines and container query timelines.
@timeline NAME {
type: media | container;
feature: <media-feature-name> | <container-feature-name>;
from: <value>; /* 0% of the timeline */
to: <value>; /* 100% of the timeline */
container: <'container'>; /* only applies to container query timelines,
same seeking function as container queries */
}
While query-linked timelines can be referenced in animation-timeline, it's not recommended to use this method in most cases because it would cause cascading problem: anyone using query-based interpolation via animation properties would override all affected properties at levels of the cascade.
They can, however, be referenced by an interpolation function within the affected property declarations, which allows the interpolated value to cascade the same as any other declared value.
Value Interpolation
Value interpolation uses a percentage value to indicate how close or far from the start/end points to calculate the interpolated value. Interpolation is interpreted through an easing curve, and the input percentage can be selected based on the current position on a timeline such as a query timeline.
Timeline-based Value Interpolation
This extends the generic interpolation function adopted (but as yet unnamed ;) in #581
By naming a timeline instead of giving a percentage directly (see percentage mixes in #581 (comment)), the author can use progress along a timeline as the progress percentage. Any value valid for animation-timeline or any timeline name defined via @timeline is valid, which allows the mix() to respond to query-linked timelines and scroll-linked timelines.
Value Interpolation with Keyframes
For more complex interpolation curves, the <start-value> and <end-value> can be replaced by a reference to a named set of keyframes.
mix( [ <timeline> && [ by <easing-function> ]? && of <animation-name> ] )
Note: Using keyword markers (as in gradients) allows the arguments to be reordered, so that authors don't have to memorize positions of arguments.
Reacted by Scott Kellum, Vaibhav Khulbe, Trys Mudford, Adam Argyle, Johannes Odland and jonjohnjohnson
As an addendum: for CSS @scroll-timeline — as specced in the Scroll-Linked Animations spec — the authors explicitly moved away from using start(here named from) and end(there named to) as descriptors.
They replaced it with one descriptor named scroll-offsets(which here could be named offsets), that accepts an array of values.
As per spec:
Scroll timeline offsets determine the effective scroll offsets in the direction specified by orientation that constitute the equally-distanced in progress intervals in which the timeline is active.
That way they allow more than two offset to be used.
@bramus If I understand right, we're thinking about timelines a bit differently here. They seem to be establishing the number and placement of keyframes in the timeline description, and that seems to me like the wrong location for that information.
In our proposal, the timeline doesn't establish the available keyframes, just the distance that we travel from 0% complete to 100% complete. Then authors can attach that to an animation or interpolation function with as many keyframes as they need. The individual offset concerns of each animation ("reveal, "unreveal", etc) are handled in keyframes, rather than in the timeline itself. So you have a single timeline (x to y), and then the ability to offset keyframes within that timeline. "Reveal" might happen between 20%-40% of the timeline, and "unreveal" happens from 60%-80%, each one using as many keyframes as it wants.
The number and placement of keyframes is controlled by the animation/interpolation rather than by the timeline.
@mirisuzanne You understand correctly there. Simply wanted to point out that “this move in the other direction” was made before, and that it perhaps could be relevant to take into account ;)
The CSS Working Group just discussed interpolating values between breakpoints, and agreed to the following:
RESOLVED: Accept mix() function into Values 5
The full IRC log of that discussion
<TabAtkins> Topic: interpolating values between breakpoints
<TabAtkins> github: https://github.com//issues/6245
<fantasai> https://github.com//issues/6245#issuecomment-926351855
<TabAtkins> miriam: This is building on that same idea, but creating timelines out of MQ/CQs
<TabAtkins> miriam: In this caes you're more often doing interpolated values based on the timeline, not animations specifically
<flackr> q+
<TabAtkins> miriam: We want to be able to create timelines off the size of the container
<TabAtkins> miriam: So for defining the query timeline, we have an @timeline syntax.
<smfr> q+
<TabAtkins> miriam: Give it a name, say what we're querying, what feature we're querying
<TabAtkins> miriam: And give it a from/to value to offset that range
<TabAtkins> miriam: So interp between a container being 100px and 40em to define the timeline
<TabAtkins> miriam: If it's a CQ we give the name of the container
<TabAtkins> miriam: If there are multiple CQs with that name this'll apply to all of them
<TabAtkins> miriam: Kids will look at their appropriate ancestor container
<TabAtkins> miriam: And we can use the timeline name in an animation-timeline
<TabAtkins> miriam: But more often we'll want a value that interps in the cascade instead, so we can override it if we need to
<TabAtkins> miriam: A generic interpolate() function has been discussed for a long time
<TabAtkins> miriam: We called in mix() here, named TBD
<TabAtkins> miriam: Idea is it could be generic, taking a %, or take a timeline which resolves to a %. Could invoke scroll timelines too, etc.
<TabAtkins> miriam: And then it takes an easing function and two values to interp between
<TabAtkins> miriam: In some cases this'll get more complex with multiple values, maybe get quite long
<TabAtkins> miriam: Wondered if mix() could ref keyframes
<TabAtkins> miriam: So you could pull out the value details into keyframes for more detailed control
<TabAtkins> fantasai: I wanted to point out the cascade effects
<chris> q+ to wonder about once more doing piecewise functions with no continuity
<TabAtkins> fantasai: We considered putting query-based timelines as a value of aniamtion-timeline
<TabAtkins> fantasai: That ends up applyin all the props at once, and at an overriding level of the cascade
<TabAtkins> fantasai: Usually you don't want that, you just want to specify a value at a normal cascade spot, but *based on* a timeline
<TabAtkins> fantasai: So my font-size timeline can just spec an interpolated normal font size, and then have an overriding rule setting the font-size to a specific value as normal.
<Rossen_> ack fantasai
<Zakim> fantasai, you wanted to react to flackr to point out cascade effects
<Rossen_> ack flackr
<fantasai> s/as normal/as usual in the cascade/
<TabAtkins> flackr: I think what fantasai just said might change my q...
<TabAtkins> flackr: So this isn't an animation timeline, it only exists for the mix() function?
<TabAtkins> fantasai: We were debating that.
<TabAtkins> fantasai: We definitely want it for mix(). Whether it's available for animation-timeline is an open question
<TabAtkins> fantasai: We've asked brian for feedback and he pointed out there were a lot of complexities, so we might not want to do it
<TabAtkins> fantasai: Not the most important; mix() is the primary case
<TabAtkins> flackr: Yeah was gonna raise the same complexities; if it's animation, we have to have the animation progress update in the middle of the cascade.
<TabAtkins> flackr: Anders said it would be a huge technical burden to have anims update as part of the cascade due to the cascade
<TabAtkins> smfr: This feels like calc() to me
<Rossen_> ack smfr
<TabAtkins> smfr: We could have one that interps with easing funcs
<TabAtkins> smfr: Missing piece is input from media features, could come in as env()
<TabAtkins> smfr: And so with a calc easing function thing
<fantasai> TabAtkins: not quite, implies only doing calc()-able things
<fantasai> TabAtkins: not all things that can be interpolated
<fantasai> TabAtkins: which includes colors, etc.
<fantasai> smfr: Can we make calc() accept these things?
<fantasai> TabAtkins: I don't want to but we can talk about it?
<Rossen_> ack chris
<Zakim> chris, you wanted to wonder about once more doing piecewise functions with no continuity
<TabAtkins> chris: So this is unpopular
<TabAtkins> chris: We start by lerping two values
<TabAtkins> chris: Then we add more values and lerp them
<TabAtkins> chris: And if you draw that it's jaggy on a graph because slopes are different
<TabAtkins> chris: And then we add easings, and you can maybe fake it to look continuous
<TabAtkins> chris: But we never get to a thing that smoothly interpolates thru N values
<TabAtkins> chris: Is that something we want to do or just continue keeping it pairwise?
<TabAtkins> flackr: Is this not having easing on the mix function?
<TabAtkins> chris: That requires the author to figure out C1 continuity on their own
<TabAtkins> fantasai: This seems compatible with what keyframes do right now, we could default to smooth interp
<TabAtkins> TabAtkins: So chris's request is for the abilty to spec an animation with N values and have it automatically smoothly interp, rather than only having pairwise interp control that needs manual adjustment
<TabAtkins> chris: yes
<TabAtkins> TabAtkins: c1 continuity, to be specific
<fantasai> fantasai: We specced multi-stop animations using @Keyframes, see last section of proposal
<Rossen_> q?
<fantasai> TabAtkins: I suspect that's something we can handle at a higher level
<fantasai> TabAtkins: we have a default for pairwise interpolation, default to ?
<fantasai> TabAtkins: could do smarter things in animations
<fantasai> TabAtkins: fits within existing syntax structure of animations
<fantasai> flackr: It will be challenging, though
<fantasai> flackr: easing function per keyframe is just between those endpoints
<fantasai> flackr: easin function on animation is just input time to output time
<fantasai> TabAtkins: animation-easing-function is the default between frames
<fantasai> flackr: that's correct for CSS. Web Animations also adds an easing curve to the timeline
<fantasai> TabAtkins: you're easing time into massaged version, that's separate from this
<Rossen_> ack fantasai
<TabAtkins> fantasai: i think we could easily have a "tweak the time"-based version, we could add that into the rule as well
<fantasai> s/rule/@timeline rule/
<fantasai> fantasai: Intention of mix() argument was the default easing between frames
<fantasai> fantasai: If we want to default to doing continuous magic, or adding a keyword to opt into it, that's fine
<TabAtkins> flackr: Yeah it would be like combining adjacent pairs that have the same value into one continuous timing function
<TabAtkins> fantasai: I want to point out we dont' ahve a resolution on the form of the generic interp function
<TabAtkins> fantasai: So our proposal is to have it accept %s and two values
<fantasai> https://github.com//issues/581#issuecomment-926353789
<TabAtkins> fantasai: So this would be a function that replaces the % with a timeline that computes to a %
<TabAtkins> fantasai: We have a resolution to *add* a mix() function but didn't settle on the syntax
<TabAtkins> Rossen_: So what can we resolve on?
<fantasai> s/this would be/this proposal is/
<TabAtkins> fantasai: resolution the first: generic interpolate function is called mix(). Takes %, then start value, then end value. Values are separated with semicolons to avoid ambiguity with comma-containing values
<TabAtkins> (you can interp a comma-separated list, for example)
<TabAtkins> TabAtkins: Simon had some thoughts about this in calc(), do you want to continue talkinga bout this?
<TabAtkins> smfr: I'm not quite sold on @timeline yet, but I don't want to stall this
<fantasai> https://github.com//issues/581
<TabAtkins> fantasai: Right now it's just mix()
<TabAtkins> smfr: Would this be like a calc()?
<TabAtkins> fantasai: Like, but wider.
<fantasai> fantasai: It has to be able to interpolate every possible computed value in the entire space of CSS
<TabAtkins> smfr: It requires UAs to have a parallel version of calc trees, for every possible value
<TabAtkins> fantasai: You kinda already have that since everything can interp
<TabAtkins> fantasai: Like, how do you interp between currentcolor and blue? No way to represent that right now. (color-mix() is coming, but this is a wider issue)
<TabAtkins> fantasai: So we have lots of places where we want to interp things that don't have intermediate values
<TabAtkins> smfr: That makes sense, we also invented cross-fade() to hit the image case
<TabAtkins> smfr: I'd like to hear from other impls about their thoughts on impl complexity, and whether it makes sense to think of it in terms of calc()
<fantasai> TabAtkins: I don't have problem of thinking about it in terms of calc(), can re-use machinery there
<fantasai> TabAtkins: but I think that's an internal detail
<TabAtkins> fantasai: Note that we *resolved* to add the function years ago but didn't resolve on the syntax
<fantasai> see also https://github.com//issues/2854
<TabAtkins> RESOLVED: Accept mix() function into Values 5
<Rossen_> s/Accept mix() function into Values 5/Accept mix() function into Values 4/
<TabAtkins> fantasai: So next is do we want mix() to accept a timeline+easing function instead of a %
<TabAtkins> fantasai: If no, I don't need to go into details. If yes, we'd use the @timeline rule discussed previously.
<TabAtkins> TabAtkins: This just got proposed last week, it's a little big. I'd like more time to review on it.
<TabAtkins> fantasai: And this would def go into level 5
<fantasai> ScribeNick: fantasai
In the section on transform-mix(): As an aid to readers, suggest linking to the matrix interpolation algorithms in transforms-1 and transforms-2.
Yup, done.
Specific points I'll call out:
We added some examples to the intro, I think these address all your points. If you have further suggestions, let us know or drop a PR. ^_^
7.2.2 uses the term "pinned" which I haven't seen elsewhere. How does it differ from "clamped"? Some examples of the effect of pinning might be helpful.
Switched to "assigned"; it's just setting the 0%/100% points on the interpolation range.
Reading "300px in hsl" without having yet wrapped my brain around the grammar threw me for a loop.
can calc-interpolate() and calc-mix() be resolved during simplification?
Yes, this is specified in 7.3 Interpolation Resolution for interpolation. It's now specified in "Mix Resolution" as well, using nearly identical wording.
6.2 and 7.3 are only about the computed/used value. I forget to ask specifically for a declared value... sorry. I guess only <calc-sum>s must be simplified. No normalization.
The CSS Working Group just discussed Interpolate values between breakpoints, and agreed to the following:
RESOLVED: Republish the WD
The full IRC log of that discussion
<fantasai> https://drafts.csswg.org/css-values-5/#mixing
<emilio> fantasai: we split mix function in two categories, mix and interpolation
<emilio> ... where mix() produce weighed averages
<emilio> ... interpolate creates a mapping
<emilio> ... where progress and stops and options of how you interpolate
<emilio> ... that's currently spec'd out
<fantasai> interpolate(<progress>, [ <position> : <value> ]#)
<Rossen3> q
<emilio> ... we wanted to publish these and bring people's attention and if anyone has concerns or suggestions (re. commas or semicolons)
<emilio> ... that's kinda where things are at
<emilio> ... wanted to check-in with the WG and ask if we can update the WD
<emilio> fantasai: one of the interesting thing is that when you define a stop we allow numbers / percents / lengths
<emilio> ... when you have an absolute progress and need to create this kind of map
<emilio> ... from progress to output, the interesting case is if you're mixing percentages and absolute values
<emilio> ... so we take the first and last absolute points, and those are 0 and 100%
<emilio> ... and that's how you build the map
<emilio> ... if you have feedback on that we'd love to hear it
<emilio> q+
<miriam> q+
<weinig> q+
<fantasai> emilio: Is there any sorting of stops? E.g. in gradients.
<fantasai> emilio: at what point to percentages resolve?
<fantasai> fantasai: we pin things and then follow gradient stop fixup rules
<emilio> fantasai: we pin things then we do the gradient stop fixup rules
<Rossen3> ack emilio
<weinig> q-
<Rossen3> ack miriam
<fantasai> See https://drafts.csswg.org/css-values-5/#interpolation-normalization
<emilio> miriam: maybe tangential, but progress() returns a number between 0 and 1
<emilio> ... can it be used directly or needs to be converted to something?
<emilio> fantasai: percents and numbers are called proportional, and they get treated similarly
<emilio> ... if you have proportional input, then all the stops need to be proportional values
<emilio> ... (i.e. numbers or percents)
<emilio> RESOLVED: Republish the WD
Activity
mirisuzanne commentedon Apr 27, 2021
Yeah, this would be real useful for something like "intrinsic typography" - but I can imagine other use-cases as well. It's interesting to think about media/container "breakpoints" as keyframes in an animation, which we can then interpolate (with easing).
My immediate association is scroll-timeline. I wonder if there would be a way to adapt something similar to get, basically, a container-timeline.
fantasai commentedon Sep 24, 2021
@mirisuzanne and I put together this proposal for defining and using query-linked timelines as part of rethinking various features for animation timelines and interpolation and how to fit them all together.
Query-linked Timelines
Query-linked interpolation uses a set of keyframes (minimally, two) to interpolate values along an easing curve based on the value of a query (such as a media query or container query). The timeline is therefore defined by the value of the query, and can be referenced by an interpolation function in individual property declarations.
Defining the Query Timeline
The
@timelinerule defines a named timeline. It can be expanded later to define other types of timelines, but here we're defining only two types: media query timelines and container query timelines.A typical example might look like:
While query-linked timelines can be referenced in
animation-timeline, it's not recommended to use this method in most cases because it would cause cascading problem: anyone using query-based interpolation via animation properties would override all affected properties at levels of the cascade.They can, however, be referenced by an interpolation function within the affected property declarations, which allows the interpolated value to cascade the same as any other declared value.
Value Interpolation
Value interpolation uses a percentage value to indicate how close or far from the start/end points to calculate the interpolated value. Interpolation is interpreted through an easing curve, and the input percentage can be selected based on the current position on a timeline such as a query timeline.
Timeline-based Value Interpolation
This extends the generic interpolation function adopted (but as yet unnamed ;) in #581
By naming a timeline instead of giving a percentage directly (see percentage mixes in #581 (comment)), the author can use progress along a timeline as the progress percentage. Any value valid for
animation-timelineor any timeline name defined via@timelineis valid, which allows themix()to respond to query-linked timelines and scroll-linked timelines.Value Interpolation with Keyframes
For more complex interpolation curves, the
<start-value>and<end-value>can be replaced by a reference to a named set of keyframes.Note: Using keyword markers (as in gradients) allows the arguments to be reordered, so that authors don't have to memorize positions of arguments.
bramus commentedon Sep 24, 2021
As an addendum: for CSS
@scroll-timeline— as specced in the Scroll-Linked Animations spec — the authors explicitly moved away from usingstart(here namedfrom) andend(there namedto) as descriptors.They replaced it with one descriptor named
scroll-offsets(which here could be namedoffsets), that accepts an array of values.As per spec:
That way they allow more than two offset to be used.
Relevant Issue: #4912, specifically this comment.
mirisuzanne commentedon Sep 24, 2021
@bramus If I understand right, we're thinking about timelines a bit differently here. They seem to be establishing the number and placement of keyframes in the timeline description, and that seems to me like the wrong location for that information.
In our proposal, the timeline doesn't establish the available keyframes, just the distance that we travel from 0% complete to 100% complete. Then authors can attach that to an animation or interpolation function with as many keyframes as they need. The individual offset concerns of each animation ("reveal, "unreveal", etc) are handled in keyframes, rather than in the timeline itself. So you have a single timeline (x to y), and then the ability to offset keyframes within that timeline. "Reveal" might happen between 20%-40% of the timeline, and "unreveal" happens from 60%-80%, each one using as many keyframes as it wants.
The number and placement of keyframes is controlled by the animation/interpolation rather than by the timeline.
But maybe I'm misunderstanding something there?
bramus commentedon Sep 26, 2021
@mirisuzanne You understand correctly there. Simply wanted to point out that “this move in the other direction” was made before, and that it perhaps could be relevant to take into account ;)
css-meeting-bot commentedon Sep 29, 2021
The CSS Working Group just discussed
interpolating values between breakpoints, and agreed to the following:RESOLVED: Accept mix() function into Values 5The full IRC log of that discussion
<TabAtkins> Topic: interpolating values between breakpoints<TabAtkins> github: https://github.com//issues/6245
<fantasai> https://github.com//issues/6245#issuecomment-926351855
<TabAtkins> miriam: This is building on that same idea, but creating timelines out of MQ/CQs
<TabAtkins> miriam: In this caes you're more often doing interpolated values based on the timeline, not animations specifically
<flackr> q+
<TabAtkins> miriam: We want to be able to create timelines off the size of the container
<TabAtkins> miriam: So for defining the query timeline, we have an @timeline syntax.
<smfr> q+
<TabAtkins> miriam: Give it a name, say what we're querying, what feature we're querying
<TabAtkins> miriam: And give it a from/to value to offset that range
<TabAtkins> miriam: So interp between a container being 100px and 40em to define the timeline
<TabAtkins> miriam: If it's a CQ we give the name of the container
<TabAtkins> miriam: If there are multiple CQs with that name this'll apply to all of them
<TabAtkins> miriam: Kids will look at their appropriate ancestor container
<TabAtkins> miriam: And we can use the timeline name in an animation-timeline
<TabAtkins> miriam: But more often we'll want a value that interps in the cascade instead, so we can override it if we need to
<TabAtkins> miriam: A generic interpolate() function has been discussed for a long time
<TabAtkins> miriam: We called in mix() here, named TBD
<TabAtkins> miriam: Idea is it could be generic, taking a %, or take a timeline which resolves to a %. Could invoke scroll timelines too, etc.
<TabAtkins> miriam: And then it takes an easing function and two values to interp between
<TabAtkins> miriam: In some cases this'll get more complex with multiple values, maybe get quite long
<TabAtkins> miriam: Wondered if mix() could ref keyframes
<TabAtkins> miriam: So you could pull out the value details into keyframes for more detailed control
<TabAtkins> fantasai: I wanted to point out the cascade effects
<chris> q+ to wonder about once more doing piecewise functions with no continuity
<TabAtkins> fantasai: We considered putting query-based timelines as a value of aniamtion-timeline
<TabAtkins> fantasai: That ends up applyin all the props at once, and at an overriding level of the cascade
<TabAtkins> fantasai: Usually you don't want that, you just want to specify a value at a normal cascade spot, but *based on* a timeline
<TabAtkins> fantasai: So my font-size timeline can just spec an interpolated normal font size, and then have an overriding rule setting the font-size to a specific value as normal.
<Rossen_> ack fantasai
<Zakim> fantasai, you wanted to react to flackr to point out cascade effects
<Rossen_> ack flackr
<fantasai> s/as normal/as usual in the cascade/
<TabAtkins> flackr: I think what fantasai just said might change my q...
<TabAtkins> flackr: So this isn't an animation timeline, it only exists for the mix() function?
<TabAtkins> fantasai: We were debating that.
<TabAtkins> fantasai: We definitely want it for mix(). Whether it's available for animation-timeline is an open question
<TabAtkins> fantasai: We've asked brian for feedback and he pointed out there were a lot of complexities, so we might not want to do it
<TabAtkins> fantasai: Not the most important; mix() is the primary case
<TabAtkins> flackr: Yeah was gonna raise the same complexities; if it's animation, we have to have the animation progress update in the middle of the cascade.
<TabAtkins> flackr: Anders said it would be a huge technical burden to have anims update as part of the cascade due to the cascade
<TabAtkins> smfr: This feels like calc() to me
<Rossen_> ack smfr
<TabAtkins> smfr: We could have one that interps with easing funcs
<TabAtkins> smfr: Missing piece is input from media features, could come in as env()
<TabAtkins> smfr: And so with a calc easing function thing
<fantasai> TabAtkins: not quite, implies only doing calc()-able things
<fantasai> TabAtkins: not all things that can be interpolated
<fantasai> TabAtkins: which includes colors, etc.
<fantasai> smfr: Can we make calc() accept these things?
<fantasai> TabAtkins: I don't want to but we can talk about it?
<Rossen_> ack chris
<Zakim> chris, you wanted to wonder about once more doing piecewise functions with no continuity
<TabAtkins> chris: So this is unpopular
<TabAtkins> chris: We start by lerping two values
<TabAtkins> chris: Then we add more values and lerp them
<TabAtkins> chris: And if you draw that it's jaggy on a graph because slopes are different
<TabAtkins> chris: And then we add easings, and you can maybe fake it to look continuous
<TabAtkins> chris: But we never get to a thing that smoothly interpolates thru N values
<TabAtkins> chris: Is that something we want to do or just continue keeping it pairwise?
<TabAtkins> flackr: Is this not having easing on the mix function?
<TabAtkins> chris: That requires the author to figure out C1 continuity on their own
<TabAtkins> fantasai: This seems compatible with what keyframes do right now, we could default to smooth interp
<TabAtkins> TabAtkins: So chris's request is for the abilty to spec an animation with N values and have it automatically smoothly interp, rather than only having pairwise interp control that needs manual adjustment
<TabAtkins> chris: yes
<TabAtkins> TabAtkins: c1 continuity, to be specific
<fantasai> fantasai: We specced multi-stop animations using @Keyframes, see last section of proposal
<Rossen_> q?
<fantasai> TabAtkins: I suspect that's something we can handle at a higher level
<fantasai> TabAtkins: we have a default for pairwise interpolation, default to ?
<fantasai> TabAtkins: could do smarter things in animations
<fantasai> TabAtkins: fits within existing syntax structure of animations
<fantasai> flackr: It will be challenging, though
<fantasai> flackr: easing function per keyframe is just between those endpoints
<fantasai> flackr: easin function on animation is just input time to output time
<fantasai> TabAtkins: animation-easing-function is the default between frames
<fantasai> flackr: that's correct for CSS. Web Animations also adds an easing curve to the timeline
<fantasai> TabAtkins: you're easing time into massaged version, that's separate from this
<Rossen_> ack fantasai
<TabAtkins> fantasai: i think we could easily have a "tweak the time"-based version, we could add that into the rule as well
<fantasai> s/rule/@timeline rule/
<fantasai> fantasai: Intention of mix() argument was the default easing between frames
<fantasai> fantasai: If we want to default to doing continuous magic, or adding a keyword to opt into it, that's fine
<TabAtkins> flackr: Yeah it would be like combining adjacent pairs that have the same value into one continuous timing function
<TabAtkins> fantasai: I want to point out we dont' ahve a resolution on the form of the generic interp function
<TabAtkins> fantasai: So our proposal is to have it accept %s and two values
<fantasai> https://github.com//issues/581#issuecomment-926353789
<TabAtkins> fantasai: So this would be a function that replaces the % with a timeline that computes to a %
<TabAtkins> fantasai: We have a resolution to *add* a mix() function but didn't settle on the syntax
<TabAtkins> Rossen_: So what can we resolve on?
<fantasai> s/this would be/this proposal is/
<TabAtkins> fantasai: resolution the first: generic interpolate function is called mix(). Takes %, then start value, then end value. Values are separated with semicolons to avoid ambiguity with comma-containing values
<TabAtkins> (you can interp a comma-separated list, for example)
<TabAtkins> TabAtkins: Simon had some thoughts about this in calc(), do you want to continue talkinga bout this?
<TabAtkins> smfr: I'm not quite sold on @timeline yet, but I don't want to stall this
<fantasai> https://github.com//issues/581
<TabAtkins> fantasai: Right now it's just mix()
<TabAtkins> smfr: Would this be like a calc()?
<TabAtkins> fantasai: Like, but wider.
<fantasai> fantasai: It has to be able to interpolate every possible computed value in the entire space of CSS
<TabAtkins> smfr: It requires UAs to have a parallel version of calc trees, for every possible value
<TabAtkins> fantasai: You kinda already have that since everything can interp
<TabAtkins> fantasai: Like, how do you interp between currentcolor and blue? No way to represent that right now. (color-mix() is coming, but this is a wider issue)
<TabAtkins> fantasai: So we have lots of places where we want to interp things that don't have intermediate values
<TabAtkins> smfr: That makes sense, we also invented cross-fade() to hit the image case
<TabAtkins> smfr: I'd like to hear from other impls about their thoughts on impl complexity, and whether it makes sense to think of it in terms of calc()
<fantasai> TabAtkins: I don't have problem of thinking about it in terms of calc(), can re-use machinery there
<fantasai> TabAtkins: but I think that's an internal detail
<TabAtkins> fantasai: Note that we *resolved* to add the function years ago but didn't resolve on the syntax
<fantasai> see also https://github.com//issues/2854
<TabAtkins> RESOLVED: Accept mix() function into Values 5
<Rossen_> s/Accept mix() function into Values 5/Accept mix() function into Values 4/
<TabAtkins> fantasai: So next is do we want mix() to accept a timeline+easing function instead of a %
<TabAtkins> fantasai: If no, I don't need to go into details. If yes, we'd use the @timeline rule discussed previously.
<TabAtkins> TabAtkins: This just got proposed last week, it's a little big. I'd like more time to review on it.
<TabAtkins> fantasai: And this would def go into level 5
<fantasai> ScribeNick: fantasai
98 remaining items
[css-values-5] Don't make *-interpolate()'s result consistent with it…
[css-values-5] Specify default easings for *-interpolate(). #6245
[css-values-5] Specify the generic computed/used behavior for *-mix()…
tabatkins commentedon Jun 16, 2025
@kbabbitt
Yup, done.
We added some examples to the intro, I think these address all your points. If you have further suggestions, let us know or drop a PR. ^_^
Switched to "assigned"; it's just setting the 0%/100% points on the interpolation range.
Mind filing a separate issue about this?
tabatkins commentedon Jun 16, 2025
Thanks everyone for the detailed review! Agenda+ to present the updated proposal to the CSSWG and request publication. #6245 (comment)
~fantasai and TJ
[css-values-5] Refer to transform interpolation. #6245
[css-values-5][editorial] Add example, rephrase. #6245
kbabbitt commentedon Jun 17, 2025
Done. #12348
cdoublev commentedon Jun 17, 2025
Thanks!
6.2 and 7.3 are only about the computed/used value. I forget to ask specifically for a declared value... sorry. I guess only
<calc-sum>s must be simplified. No normalization.css-meeting-bot commentedon Jul 2, 2025
The CSS Working Group just discussed
Interpolate values between breakpoints, and agreed to the following:RESOLVED: Republish the WDThe full IRC log of that discussion
<fantasai> https://drafts.csswg.org/css-values-5/#mixing<emilio> fantasai: we split mix function in two categories, mix and interpolation
<emilio> ... where mix() produce weighed averages
<emilio> ... interpolate creates a mapping
<emilio> ... where progress and stops and options of how you interpolate
<emilio> ... that's currently spec'd out
<fantasai> interpolate(<progress>, [ <position> : <value> ]#)
<Rossen3> q
<emilio> ... we wanted to publish these and bring people's attention and if anyone has concerns or suggestions (re. commas or semicolons)
<emilio> ... that's kinda where things are at
<emilio> ... wanted to check-in with the WG and ask if we can update the WD
<emilio> fantasai: one of the interesting thing is that when you define a stop we allow numbers / percents / lengths
<emilio> ... when you have an absolute progress and need to create this kind of map
<emilio> ... from progress to output, the interesting case is if you're mixing percentages and absolute values
<emilio> ... so we take the first and last absolute points, and those are 0 and 100%
<emilio> ... and that's how you build the map
<emilio> ... if you have feedback on that we'd love to hear it
<emilio> q+
<miriam> q+
<weinig> q+
<fantasai> emilio: Is there any sorting of stops? E.g. in gradients.
<fantasai> emilio: at what point to percentages resolve?
<fantasai> fantasai: we pin things and then follow gradient stop fixup rules
<emilio> fantasai: we pin things then we do the gradient stop fixup rules
<Rossen3> ack emilio
<weinig> q-
<Rossen3> ack miriam
<fantasai> See https://drafts.csswg.org/css-values-5/#interpolation-normalization
<emilio> miriam: maybe tangential, but progress() returns a number between 0 and 1
<emilio> ... can it be used directly or needs to be converted to something?
<emilio> fantasai: percents and numbers are called proportional, and they get treated similarly
<emilio> ... if you have proportional input, then all the stops need to be proportional values
<emilio> ... (i.e. numbers or percents)
<emilio> RESOLVED: Republish the WD
<'animation-timeline'> does not require an absolute stop
<'animation-timeline'> does not require an absolute stop