Browser Busy Indicators
I’m doing research on the perception of speed for my Ignite Velocity talk. The perception of website speed is obviously fueled by what the user sees in the browser. While the content of a website is controlled by the website owner, the browser also provides feedback to the user. This browser feedback affects user perception of website speed. Good developers need to understand how their code affects what users see, including the browser feedback that’s triggered (or not triggered).
Let’s start by enumerating the browser’s feedback mechanisms. I’ve identified six ways that browsers give feedback when they’re busy doing some action:
- tab icon – This is typically the site’s favicon. It turns to a spinner when that tab is busy.
- status bar – Some browsers display a message about outstanding requests in the status bar.
- reload icon – The reload icon (typically a circular arrow) changes to an “X” during downloads.
- progress bar – Some browsers have a progress bar. Opera shows the fraction of completed downloads:
- network busy – iOS shows a busy indicator whenever there’s network traffic. (Technically this is outside the browser but I included it since it’s a strong visual cue at the top of the screen.)
- cursor – In some situations the cursor changes to a “progress cursor”.
The browser busy indicators are triggered during normal web surfing such as clicking links. They’re also triggered by some of the dynamic behaviors popular in today’s web pages. I came up with this list of scenarios under which to measure browser busy indicators:
- click link – Click a link to another web page.
- async script – The HTML document contains
<SCRIPT ASYNC SRC="...">.
- dynamic script before onload - The HTML document loads a script using
- dynamic iframe - Clicking a button initiates the loading of an iframe using
- dynamic script – Same as dynamic iframe but with a script.
- dynamic stylesheet - Same as dynamic iframe but with a stylesheet.
- dynamic image - Same as dynamic iframe but with an image.
- dynamic background image - Same as dynamic iframe but with a CSS background image.
- XHR – Clicking a button initiates an XMLHttpRequest.
I chose these scenarios to mimic real world situations. For example, many single page web apps use XHR – do those trigger any browser busy indicators? Photo carousels often fetch images dynamically – does the user get any feedback from the browser when that happens?
Many of the test cases didn’t trigger any of the browser busy indicators: dynamic script, dynamic stylesheet, dynamic image, dynamic background image, XHR, and long JS loop. (Except on iOS the network spinner was triggered for every test that involved an HTTP request.) I didn’t include these tests in the results table. The results for click link, async script, dynamic script before onload, and dynamic iframe are shown in the following table.
|browser||click link||async script||dynamic script
|Chrome 27 (Mac OS)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Chrome 27 (Windows)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Firefox 21 (Mac OS)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Firefox 21 (Windows)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|IE 9 (Windows)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Opera 12 (Mac OS)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Opera 12 (Windows)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Safari 6 (Mac OS)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Safari 5 (Windows)||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Chrome Mobile 26||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
|Mobile Safari 6||TSCPRN||TSCPRN||TSCPRN||TSCPRN|
Each result is essentially a bitmask indicating whether the busy indicator was triggered. For example, the first result for “Chrome 27 (Mac OS)” and the “click link” test is TSCPRN. This means the Tab icon, Status bar, and Reload icon indicators were triggered; but the Cursor, Progress bar, and Network indicators were not triggered. A few notes about the indicators:
- The network indicator is only applicable for Mobile Safari.
- The progress bar indicator is only applicable for Opera, Safari, Android, Chrome Mobile, and Mobile Safari.
- Mobile browsers don’t have tabs, status bars, nor cursors (currently) so those indicators aren’t applicable.
The purpose of these tests is to see how the browser busy indicators might affect the user’s perception of speed under different scenarios. The tests themselves are contrived, but it’s easy (and necessary) to put them in the context of a web page.
For example, if a feature involves a JSON request, which technique should be used? These browser busy indicators provide some guidance. If the JSON data is asynchronous to the user experience, such as updating stock quotes or friends’ online status, then it would be better to not trigger the browser busy indicators. Doing so would make the user pause their current actions and wonder what the web page was doing. Conversely, if the feature was synchronous to the user experience, such as opening a mail folder, then it would be better to give the user feedback that the action was being performed.
In this context we note that the dynamic iframe technique triggers busy indicators in some browsers. Therefore, this would be a bad choice for background tasks. And if it was chosen for a synchronous action it should be augmented to provide feedback across all browsers (such as a progress icon or busy spinner).
One of the biggest takeaways for me was that the progress cursor is only triggered on Windows. I find this to be a primary feedback mechanism when using the mouse – especially when clicking a link. These Mozilla bug comments seem to point to this being a Mac OS design guideline. I find it distracting on Mac OS to have to move my eye away from where I’m focusing in order to get feedback that my click was “heard”.
These busy indicators have an impact on the user’s perception of website speed. Triggering busy indicators for actions that are supposed to be in the background brings them to the user’s attention making the experience feel slower. If a user’s action is synchronous but there’s no feedback, that’s frustrating and makes the experience seem longer than it actually is. We can produce better user experiences by taking these tradeoffs into consideration and avoiding them or augmenting them depending on the situation.