CSS has a robust animation framework. It supports transitioning most properties of an element, and defining keyframes to carefully handle the timing of transitions. # Recipes ## Simulate Typing This takes a line of text and simulates typing it, showing one character at a time until the provided numbers are displayed. You will need an animation per-text (or rather, per-character ocunt). ```css @keyframes my-typing-anim { 0% { width: 0; } 100% { width: <num-chars>ch; } } .typing { font-family: monospace; width: 0; will-change: width animation: my-typing-anim <duration> 1 steps(<num-chars>, start) forwards <start-time>; } ``` # Bugs ## Safari ### State truncation at end-of-animation At least as of Safari 26.1, Safari has a bug with applying the ending state at the end of animations. This doesn't always happen, but sometimes the state you'd expect to apply at 100% ends up not applying at all. We noticed this with the [Review Board website's](https://www.reviewboard.org) terminal typing animations, where the final character was being left off a typed line. There are two ways to avoid this that I've found: 1. If you're using `steps(<num>, end)`, try seeing if you can move to `steps(<num>, start)`. This may change the animation, but it it effectively ties the animation state to the start of the animation rather than applying the last step at the end of the animation. This can avoid this bug, if it's the right fit for your animation. 2. If defining `@keyframes`, don't rely on `100% { ... }`. Instead, add a `99%, 100% { ... }` to help ensure state is applied before the animation is considered done.