In single-process Firefox, when the user switches tabs, this is a synchronous operation. The browser blocks while it loads content into the newly selected tab, then switches to that tab. It indicates that the tab is selected by setting the selected attribute on the XUL tab object. Code (including browser code, extensions, or themes) that wants to change the appearance of the selected tab can use the selected attribute to apply CSS for that tab.

In multiprocess Firefox, tab switching is asynchronous. When the user switches tabs, the chrome process sends a request to the content process to load the page into the newly selected tab. The function in the chrome process then returns immediately, so other code can run. Once the content process is ready, it sends a message back to the chrome process, which then switches tabs in the user interface.

There's also a timer in the chrome process: if the content process has not responded before the timer expires, then the browser switches tabs anyway, and just displays an empty tab containing a spinner, until the content process has finished loading the page. Currently the timer is set to 300 milliseconds.

There are, correspondingly, two attributes used to signal tab selection:

This means that code which wants to style the currently selected tab needs to use the visuallyselected attribute to do so. If it uses the selected attribute, then there will be a momentary disconnect in which the newly selected tab's style is updated, but the browser is still displaying the old tab's content.