Your milage is always going to vary between different browers. I don't think that you can accurately say one solution is going to always be the best cross browser, but what you can accurately rely on, is that anything that uses your GPU is going to be faster. When you animate using a setTimeout, the browser does all of the crunching in memory and through the CPU. Additionally, it doesn't really know that the intended animation is suposed to be smooth.
Depending on which version of your browser, you will also find that GPU acceleration can be hit or miss. For example, up until last year, a common trick to ensure that webkit based browsers always used GPU accelleration was to do a kind of "type hint" where you would set the property to be
Another point to add however, is what does "performant" actually mean for you? Does it mean visually performant, which means smooth? In which case you wouldn't want to use setTimeout, because you can't realistically get that "smoothness". So where possible, you would want to use transitionining through CSS (and rely on GPU accelleration where avaialble).
But what if you mean "performant" in terms of battery life on your device. In which case you would probably want to use
Why should I use it?
The browser can optimize concurrent animations together into a single
reflow and repaint cycle, leading to higher fidelity animation. For
example, JS-based animations synchronized with CSS transitions or SVG
SMIL. Plus, if you're running the animation loop in a tab that's not
visible, the browser won't keep it running, which means less CPU, GPU,
and memory usage, leading to much longer battery life.
Reference : requestAnimationFrame for smart animating
Next up, "performant" might mean time-spent for you. I know that personally, I can be most performant if I use CSS animations, and use them whereever possible.
This article will be a useful read for you: