Have you ever had music continue playing after switching tabs?
Or dashboards keep polling APIs while you’re not even watching?
Modern web apps often continue working unnecessarily when the tab is hidden — leading to wasted resources, wrong analytics, and a worse user experience.
This article introduces a lightweight utility that solves that problem cleanly and consistently:
@alkeshgupta/tab-visibility
Let's deep-dive into why tab visibility matters, how the browser behaves behind the scenes, and how you can leverage it in React or vanilla JavaScript immediately.
⭐ If you find this useful, consider leaving a star on GitHub!
🧠 The Hidden Problem You Don’t Notice (But Your Users Do)
When a browser tab goes into the background:
Animations keep running
Videos continue playing
Timers continue ticking
API calls keep firing
Game loops keep looping
This leads to:
🔋 Battery drain
🐌 Performance degradation
📉 Incorrect business metrics
📊 Wasted backend server resources
😡 Annoying UX (media keeps playing when tabbed away)
Developers often forget to pause/resume behavior based on tab visibility.
🔍 The Browser’s Behavior: A Quick Primer
Browsers expose the Page Visibility API, which gives:
document.visibilityStatevisibilitychange event
The state can be:
visiblehidden
When a user switches tabs, minimizes the browser, or switches focus — the event fires.
Manually handling this looks like:
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
pauseThings();
} else {
resumeThings();
}
});
But as you scale your application:
- You need multiple listeners
- You need to clean them up
- You need to debounce/throttle events
- You need media control logic
- You need consistent behavior across browsers
It gets messy!
❌ Traditional Implementation Pitfalls
Most developers:
- Forget to remove listeners
- Duplicate logic across components
- Handle blur/focus inconsistently
- Mix UI and lifecycle logic incorrectly
- Don’t centralize presence handling
Even in React, it’s easy to introduce memory leaks.
So we abstracted it.
✅ What @alkeshgupta/tab-visibility Solves
This utility:
✔️ Detects tab visibility changes
✔️ Provides clean callbacks
✔️ Supports multiple handlers
✔️ Automatically pauses <video> & <audio> elements
✔️ Works in React AND plain JavaScript
✔️ Requires zero configuration
One API to rule them all.
No boilerplate.
✨ Key Features
- onShow(callback)
- onHide(callback)
autoPauseMedia()
Multi-callback support
Works globally
Simple and intuitive
📦 Installation
npm install @alkeshgupta/tab-visibility
or
yarn add @alkeshgupta/tab-visibility
🧠 Basic Usage
import { useTabVisibility } from "@alkeshgupta/tab-visibility";
useTabVisibility.onShow(() => {
console.log("Tab is visible again!");
});
useTabVisibility.onHide(() => {
console.log("User switched tab!");
});
⚛️ React Usage Example
Works anywhere inside your components.
import { useEffect } from "react";
import { useTabVisibilityHook } from "@alkeshgupta/tab-visibility";
function MyComponent() {
useTabVisibilityHook({
onHide: () => {
console.log("User switched tab!");
},
onShow: () => {
console.log("Tab is visible again!");
},
});
return <div>Watching tab visibility</div>;
}
export default MyComponent;
You can register as many event handlers as you want.
🔊 Auto Pause Media (Video/Audio)
Automatically pause all <video> and <audio> elements when the tab becomes hidden:
import { autoPauseMedia } from "@alkeshgupta/tab-visibility";
useEffect(() => {
autoPauseMedia();
}, []);
Optional - Ignore Muted Media:
import { autoPauseMedia } from "@alkeshgupta/tab-visibility";
useEffect(() => {
autoPauseMedia({ ignoreMuted: true });
}, []);
🧩 Vanilla Example (HTML)
Works anywhere inside your components.
<script type="module">
import { useTabVisibility } from "https://cdn.jsdelivr.net/npm/@alkeshgupta/tab-visibility@1.0.1/src/index.js";
useTabVisibility.onShow(() => {
console.log("Tab is visible again!");
});
useTabVisibility.onHide(() => {
console.log("User switched tab!");
});
</script>
🧬 API Reference
onShow(callback: Function)
Registers a function to run when tab becomes visible.
onShow(() => console.log("Welcome back!"));
onHide(callback: Function)
Registers a function to run when tab becomes hidden.
onHide(() => console.log("Hey come back 👀"));
autoPauseMedia()
Pauses all video and audio elements on the page.
autoPauseMedia();
autoPauseMedia({ ignoreMuted: true })
Pauses all unmuted video and audio elements on the page.
autoPauseMedia({ ignoreMuted: true });
🧪 Testing Tip
To test locally:
- Open devtools
- Start logging visibility events
- Switch tabs
- Observe:
- event triggers
- media pausing
- batched handlers
No special instrumentation required.
🔍 When Should You Use This?
Ideal for:
- Media streaming apps
- Dashboards
- Trading charts
- Data visualizations
- Pomodoro timers
- Meeting & call apps
- Games
- Chat presence indicators
⚙️ Inside the Library (Technical Architecture)
Internally, the utility:
- Registers a single visibilitychange listener
- Stores onShow/onHide callbacks in arrays
- Executes them sequentially
- Optionally inspects DOM media nodes
- Avoids duplicate attachment
- Works globally across modules
This prevents event chaos.
🛑 Common Pitfalls (Solved)
Without this:
- You may pause media incorrectly
- Forget cleanup
- Attach listeners multiple times
- Cause memory leaks
- Miss subtle visibility states
This utility removes risk.
📉 Browser Throttling Behavior
Background tabs aggressively throttle:
setIntervalsetTimeout- JavaScript execution priority
requestAnimationFrame
So if you rely on timers — visibility is essential.
📜 Browser Support
✅ Chrome\
✅ Firefox\
✅ Edge\
✅ Safari\
✅ Opera
Uses the standard visibilitychange API, widely supported.
📏 Notes
- All callbacks can be registered multiple times.
- Order of callbacks is preserved.
- Works in frameworks (React, Next.js, etc.) after mount.
📎 Links
GitHub Repo:
https://github.com/thealkeshgupta/tab-visibility
npm Package:
https://www.npmjs.com/package/@alkeshgupta/tab-visibility
If this saved your time — please ⭐ on GitHub!
🤝 Contributing
PRs are welcome!
Add features, fix edge cases, or open an issue.
📜 License
MIT — free for commercial & personal use.
✅ Conclusion
Handling tab visibility properly:
- Saves CPU
- Reduces power consumption
- Improves UX
- Optimizes analytics
- Keeps media behavior sane
And instead of manually wiring event listeners + cleanup logic in every feature, you now have a reusable utility.
Try @alkeshgupta/tab-visibility in your next project 🚀
Top comments (0)