IE8 has strange rules for showing focus

While working on some accessible UI widgets I found strange behavior in IE8 related to when it does or doesn’t show the focus outline around an element that has focus.

When you use the focus method to set focus to a focusable element the expectation is that, in the absence of css rules to the contrary, the browser will show a focus outline around the element using its default style. This is what happens in Firefox, Chrome, and Safari. (Opera has its own set of focus problems which I didn’t investigate fully.)

There are a number of elements that are naturally focusable, such as inputs and anchors. In addition any element with a tabindex attribute equal to -1 is focusable. If the tabindex is non-negative then it is focusable and in the tab order. My test case uses list elements with tabindex of -1 or 0. I suspect that the same is true of other elements using tabindex.

Older versions of IE (I tested IE6 and I believe IE7 works the same in this regard) had some strange additional requirements beyond just calling focus. The outline would not be shown if the focus method was used to give focus to an element with a tabindex of -1. So before setting focus you would have to set the tabIndex to zero (or a positive number).

elem.tabIndex = 0;
elem.focus();

Also if you click on an element with tabindex of -1 no outline is shown unless the className is updated (even if the value doesn’t change). Perhaps other style changes would work as well.

IE8 adds some new bizarre behavior. First if css is used to set an explicit outline style on the elements (either directly or inherited) then the old IE quirks mentioned above go away as well as the new IE8 problem described below. Setting your own outline style for focus isn’t a good idea unless you are giving your whole web app a focus style makeover. I think it is best to stick with the default styles since it is what the user is probably used to. There is also the problem of old browser like IE6 not supporting the outline style.

If the className of the element receiving focus is updated in the onfocus handler while the tabIndex is -1 then no focus outline is shown. Assuming that the tabIndex is -1 and addClass is a function that adds a class to the className, one would expect the following two lines of code could be executed in either order.

addClass(elem, "myfocus");
elem.tabIndex = 0;

In IE8 setting the tabIndex to zero must be done first or the outline is not shown. This is exactly what tripped me up. If I just happened to write the statements in the opposite order I would never have discovered these oddities.

Note that in all cases focus is actually set correctly it is just the visual indication of focus that is wrong – but thats the important part of focus.

I created a test page that allows playing around with these rules. It is also an example of how focus can be managed with a roving tabindex. If you play with this page in different browsers you will notice that in Firefox (versions 2 – 3.5) , Chrome, and Safari 4 (I tested on Windows) it doesn’t matter what options are checked, the behavior is correct. In IE you can play with the options to see which combinations work.

I wonder if this is intentional in IE8 or is something that will get fixed in a point release.