Mobile browsers may look like desktop browsers, but their
behavior sometimes is different and we need to understand them to
provide the right user experience. In this post I’ll show you a
trick to notify the user about an update while our website is on a
background tab.

At the top, Chrome for desktop
showing updates on background tabs; at the bottom, Safari for iPad
freezing background tabs
While on desktop browsers, we can keep multiple running tabs, on
most mobile browsers timers (and all JavaScript execution) are
paused when the web page left the foreground status.
If you have an iPad, let’s say you have your webmail open in one
tab. When you want to browse to another website, you open a new
one. That means your email will be frozen for several hours or even
days and you will never get updates, until you go back to that
tab.
As developers, this raises an important issue: Is there any
way to update the content and notify the user while the tab is in
the background? As you can see with an iOS device at http://ad.ag/pdtdpw,
I’ve found a solution.
UPDATE: The quick explanation on how this hacks works
is:
Safari on iOS freezes inactive tabs, but it honors the
refresh meta declaration. After a reload, the tab is alive again
while it is still in the background. A kind of “background tab
resurrection” process.
Updating a background tab on iPad
After making some research and testing, I’ve found a
good solution compatible with iPad to notify the user of
an update when the tab is in the background: our old friend,
the meta refresh.
While it can be an annoying behavior from a user’s perspective
when the page is active, the old HTML mechanism allows us to define
a meta tag to reload a window automatically every n
seconds. Some browsers, such as Safari on iOS, allow us to use this
hack to automatically reload inactive tabs and keep them
updated:
<!-- Updates the page every 1 minute -->
<meta http-equiv="refresh" content="60">
With this technique, the page will reload on the iPad and the
inline scripts and the onload event will be executed in the
background tab on every version of iOS. On iOS 5.x no other event
or timer will be executed after the onload event until the user
goes back to activate the tab. On iOS 6.x timers continue
executing even in the background after an automatic
refresh.
Refreshing the tab only when in background
The problem is how to remove the reload behavior when the page
is the active tab and the user is using our website. Every time we
set the content attribute dynamically in the
meta tag, the browser starts counting again, so we shift the next
reload hit. We can use this idea then to not refresh the page all
the time.
To make the trick work on the iPad, we can start a
chronometer that will shift the refresh meta tag n seconds on every
execution. While the page is still active, our chronometer will
be executed and the reload action will be shifted every n seconds.
When the page goes onto a background tab, the chronometer will not
be fired and the refresh meta tag will trigger, refreshing the page
once. From iOS 6.1, after the refresh, the chronometer will
continue executing pausing more reloads:
<!-- Updates the page every 1 minute -->
<meta http-equiv="refresh" content="60"
id="metarefresh">
<script>
// iPad background tab notification trick
var mr = document.getElementById("metarefresh");
setInterval(function() {
mr.content=mr.content; // Shift the reload operation
}, parseInt(mr.content)/2); // Every 30 seconds in our
example
</script>
Creating a background notification
iOS doesn’t support the Web
Notifications API as BlackBerry 10, Firefox for Android, Amazon
Silk 2.0 and Firefox OS.
Unfortunately, Safari for iPad doesn’t make use of a favicon in
the tab UI so our only option is to use the title element to update
the UI and capture the user’s attention. Therefore we can
change document.title to send
information to the user via the tab’s title.
Therefore, if we just execute a chronometer and update the
title, it will just work after the background reload. For
example:
<script>
var count = 0;
setInterval(function() {
document.title = count;
count++
}, 1000);
</script>
In this example, the counter will start from scratch every time
we move the tab to the background as it reloads once. We can use
sessionStorage to maintain values between reloads.
Chrome for Android supports background execution directly;
therefore these tricks are not necessary. Table 12-1 shows the background
execution behavior in different browsers.
What about iPhone?
I’m not sure yet if this is good news or bad
news: we can use window.alert from a background
tab that was refreshed and it works! And this trick
also works on iPhone where there are no tabs but background
windows. But be careful, it’s a very intrusive dialog from a
background tab or window. If it’s an iPad, changing the title for
the tab seems like a better idea.
For iPhone or iPod touch we can then refresh the page and
generate an alert dialog if there is something important we want to
say. However, there is no way to automatic move the active window
to ours; so the alert message should indicate that to see what’s
happening the user should move to our window.
Change the title only when in background
In this example, the title is being updated all the time, even
when the tab is in foreground. To change that, we need a way to
separate foreground from background state after a reload. Without
Page Visibility API it seems complicate. I have even tried
with Animation Timing API,
also known as requestAnimationFrame and even in the
background, frames are being fired. At the time of this writing I
couldn’t find an easy way to differentiate between
foreground state and background after a reload state.
If you find a way, just add a comment in this post.
But it doesn’t work on iOS 6.0 and 5.x!
The previous code works perfect on iPad with iOS 6.1+ but on iOS
6.0 and 5.x it’s a different story. Because timers don’t fire
after the reload, we need a different approach. The approach
on iOS <= 6.0 is to just update the title when the page is being
loaded and leave the meta refresh make its work every n seconds. In
the count example, we can just use sessionStorage.
<script>
var count = sessionStorage.getItem("count")||0;
document.title = count;
count++
sessionStorage.setItem("count", count);
</script>
In this case we don’t have the problem as in iOS 6+ and we can
update the title only in the background.
Try it yourself
If you have an iOS device with you, just go to http://ad.ag/pdtdpw
This post was partially extracted from
my book Programming the Mobile Web, 2nd.
edition published in 2013 by O’Reilly Media.
More about tabs
On future posts I’ll continue talking about background tab
management for mobile devices, including page visibility detection.
If you can’t wait to that time, remember my book Programming the Mobile Web, 2nd edition
has +750 pages on the topic :) This is a series of posts I’m
publishing based on content extracted from that book.