Here's what the spec says:
Notably, they can even be transitioned or animated, but since the UA has no way to interpret their contents, they always use the "flips at 50%" behavior that is used for any other pair of values that can’t be intelligently interpolated. However, any custom property used in a @keyframes rule becomes animation-tainted, which affects how it is treated when referred to via the var()function in an animation property.
(this is theory, not Chrome practice quite yet)
- you can refer to custom properties in transition or animation endpoints, they'll "just work" (example)
- you can animate custom properties, but they will 50% flip between keyframes
- you can't substitute a custom property into any of the animation or transition properties if you use it in any keyframe anywhere on the page (that last point is the tainting referred to in the spec)
Take something simple first, like this:
.foo {
transition: --a 1s;
--a: "hi there";
}
.foo:hover {
--a: 42;
}
If I hover over a .foo, then for 500ms the value of --a will be "hi there", and after that it'll be 42. Now extrapolate to animation keyframes :D
In custom properties v1 there can't be - we don't know what the type of the token stream is. In Houdini properties & values, though, we extend the model by allowing you to register a type and that lets us animate them properly. You can read more about Houdini and typed CSS in this awesome post by fellow devrelian Surma.