Skip to Content
Course content

214: The Page Visibility API

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I once worked with a junior dev who spent an entire weekend trying to figure out why our staging server was crashing every Tuesday morning. He’d written a really slick real-time dashboard that polled an API every three seconds to update a set of stock tickers. It worked perfectly during his tests. But as it turns out, a few of our internal testers had the dashboard open in a background tab for eight hours a day. Even though they weren't looking at the page, the browser kept firing those requests. We essentially DDOSed our own server because the app didn't know it was invisible.

That's where the Page Visibility API comes in. It’s a small but powerful tool that tells your code whether the user is actually looking at your page or if they've switched tabs, minimized the window, or locked their screen. Instead of blindly running heavy processes, you can actually be a "good citizen" of the browser and the network.

Tracking the Visibility State

The core of this API is the document.visibilityState property. It doesn't just return a boolean; it gives you a string. Most of the time, you're looking for 'visible' or 'hidden'. While there used to be a document.hidden property, it's largely been superseded by the more descriptive state string.

The real magic, however, happens when you listen for the visibilitychange event. This event fires every time the state flips. I usually set this up as a global listener early in the application lifecycle so I can toggle global flags for things like animations or API polling.

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    console.log('Tab is out of sight. Time to relax.');
    // Stop the heavy lifting here
  } else {
    console.log('Welcome back! Resuming work.');
    // Kick things back into gear
  }
});

Optimizing Resource Consumption

You might be wondering, "Doesn't the browser already throttle timers in background tabs?" It does, but it's inconsistent across different browsers and OS power-saving modes. Relying on the browser's default throttling is a gamble; using the Visibility API is a strategy.

I typically use this for three specific things: pausing requestAnimationFrame loops to save GPU/CPU, stopping setInterval polls to save server bandwidth, and pausing video or audio playback if the UX demands it. For example, if you're building a chat app, you might stop polling for new messages and instead switch to a "catch-up" fetch the moment the user returns to the tab.

let pollInterval;

function startPolling() {
  pollInterval = setInterval(async () => {
    const data = await fetch('/api/updates');
    console.log('Updating UI with new data...');
  }, 5000);
}

function stopPolling() {
  clearInterval(pollInterval);
}

document.addEventListener('visibilitychange', () => {
  document.visibilityState === 'visible' ? startPolling() : stopPolling();
});

// Start polling initially if the page starts as visible
if (document.visibilityState === 'visible') {
  startPolling();
}

It's a simple pattern, but it prevents those "why is my laptop fan screaming?" moments for your users.




📋 Practical Task

Build a Resource-Aware Stopwatch

Your task is to create a stopwatch that tracks elapsed time. However, to save system resources, the stopwatch should stop updating the DOM (the visual timer) whenever the tab is hidden, and it should log a message to the console stating "Pause: Tab Hidden" and "Resume: Tab Visible".

Requirements:

  • Create a simple HTML page with a display for the timer (e.g., <div id="timer">0s</div>).
  • Implement a setInterval that increments the timer every second.
  • Use the visibilitychange event to stop the timer's UI updates when the tab is hidden and restart them when it becomes visible.
  • Ensure the actual elapsed time continues to be tracked internally, so when the user returns, the timer reflects the correct total time passed, even if the visual updates were paused.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.