🏠 back to Observable

safari framerate cap in rendered notebooks pre-interaction

Apparently Safari limits framerate (of requestAnimationFrame, setInterval, etc.) to 30 fps for any iframe that the user has not explicitly interacted with. [After user interaction, requestAnimationFrame jumps to 60 fps, and other loops go to whatever speed the machine can handle.]

See the comments at:

Or experiment with (e.g. compare before/after clicking the ‘restart’ button):

Does anyone have ideas for working around this, maybe something that could be done at platform level?

The simplest notebook-author workaround is to make sure that anyone who is going to look at an animation in a notebook that needs to be very smooth should first click a button or drag a slider or something. But there are a lot of notebooks out there which include animations but no user interaction per se, and I suspect most authors won’t even consider that Safari viewers are getting limited to 30 fps.

1 Like

Short of a Call-to-Action, I don’t expect there’s anything that can be done. For animations you can resort to a “play” CTA (either as a button, or an overlay in your chart), or require the user to make an explicit choice (e.g. data source, variable).

This could be made optional by measuring the delay, which however may also be impacted by other factors. Perhaps a helper that can be imported and injected into a chart DOM.

Outside of Observable the workaround would be to not embed the notebook as an iframe, but load and run the module directly.

Does this limitation also apply to postMessage-based solutions?


1 Like

Thanks for the suggestion! I’ve updated the FPS Counter notebook to include an example for postMessage(). The counting seems to be somewhat off, but it seems that Safari will also throttle message events.