Listen for visibilitychange (or the platform SDK’s pause event) and toggle a single isPaused flag that stops your update loop, timers and audio, then resumes them on visible/resume. Audio needs an explicit resume call because browsers don’t restart it automatically.
At a glance
| Fact | Value | Source |
|---|---|---|
| Native browser event for tab switching | visibilitychange | developer.mozilla.org |
| Unity WebGL talks to JS via | .jslib plugin | docs.unity3d.com |
| Godot 4 web bridge to JS | JavaScriptBridge singleton | docs.godotengine.org |
In vanilla JS, bind to document.visibilitychange and check document.hidden, then pause your update loop, physics step and any setInterval/setTimeout timers. On resume, don’t just un-pause: reset your delta-time clock first, or the next frame will try to simulate the entire hidden duration in a single step.
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
game.pause();
} else {
game.resetClock();
game.resume();
}
});
Audio is the part people forget: browsers typically leave an AudioContext or <audio> element running or resume it unexpectedly when the tab regains focus, so mute or explicitly stop it on hide and resume it yourself on show rather than assuming it follows the game state.
What about game engines?
In Unity WebGL you can’t read the Page Visibility API directly from C#; write a small .jslib plugin that forwards visibilitychange into a callback (see Unity’s browser scripting docs). In Godot 4 web exports, use the JavaScriptBridge singleton to hook the same browser event.
If you use Playgama Bridge, listen for PAUSE_STATE_CHANGED to pause gameplay, timers and audio across engines.
Sources
- Playgama Bridge: Platform API
- Playgama wiki: Sound does not pause when switching browser tabs
- Unity manual: interacting with browser scripting
- Godot docs: exporting for the Web
- MDN: Game development
Related questions
Why does audio keep playing after I pause the game on tab switch?
Browsers don’t automatically stop AudioContext or audio elements on visibilitychange; you must explicitly mute or stop audio in your handler and resume it yourself when the tab becomes visible.
Should I use requestAnimationFrame or setInterval for the game loop?
requestAnimationFrame automatically throttles in hidden tabs, which helps, but you still need a visibilitychange handler to pause physics and timers deterministically.
Last updated: 24 September 2026