Partial Keyframes A CSS keyframe animation can still function even if the `from` or `to` block is omitted. When the starting point is missing, the animation inherits the element's current property value (like opacity) rather than snapping to a predefined starting point. This technique makes keyframe animations dynamic and composable, allowing them to adapt to an element's existing styles or state. The most common way to write a CSS keyframe animation is to specify a starting point and an ending point, using from and to : @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } What do you suppose happens if we omit one of these blocks? For example, what if we only specify the ending point? @keyframes fadeToTransparent { to { opacity: 0; } } This still works Even without defining a starting opacity, our element will still fade out when this keyframe animation is applied. When I discovered this pattern a few years ago, I thought it was a neat little trick to shave a few bytes off my bundles, a more concise way to write keyframe animations. But it turns out, there’s a way more significant and exciting benefit to this pattern This lil’ trick unlocks a hidden capability within keyframe animations that makes them dynamic and composable. ✨ In this tutorial, I’ll show you how this trick works, and we’ll explore some of the cool things we can do with it. There’s also a bonus tip at the end, showcasing how modern CSS makes keyframe animations even more powerful 😄 Link to this headingInherited values When we omit the from block from our keyframe animation, the animation’s starting values will be inherited from context. This’ll be easier to explain with a demo. Check this out: @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } Our “traditional” setup really only works for elements that are fully opaque by default, like that first yellow ball. The others immediately snap to full opacity before gradually fading out: By contrast, when we omit the from part of the keyframe, the animation will inherit the element’s current opacity and start fading from there. 🤯 We can visualize this difference with a graph: Here’s a playground with the full code, in case you wanted to poke at this a bit: Code Playground