Saturday, 20 October 2012

IE9, :focus and a strange bug

So earlier @laurakalbag posted about a problem she's having on her site...



When you first visit the site on IE9 it looks as such:



But if you put focus on to something (it's hard to see, but I've applied focus to the first of the thumbnails) it returns to look like this:



What's worse is if you click on a div, it ends up like this!



Seems like a very odd one, and worth keeping a note of.

First of all, you need to realise that IE9 (and probably IE8 and IE7 at least) all allow you to "focus" on most elements, not just on those that should be able to receive traditional focus such as links or inputs. This is different from how webkit and mozilla seem to operate.

Next, IE9 automatically puts focus on the body when the page is loaded. In the case of @laurakalbag her site had a css rule for ":focus", which is naturally applied to any element that the browser deems to have focus...including the body or divs.

This is where the weirdness properly starts though. The reason for the change in state is because when focus is applied somewhere, the body element obviously loses focus. This allows it's background colour (a purple) to return, no longer over-ridden by a semi-transparent black (looks light grey).

Now it's understandable that where a css property hasn't already been defined, it being defined in the focus attribute will make it change (such as the box-sizing attribute, that causes the div to contract in the third screenshot above). What is truly strange is how IE treats the order of importance of CSS attributes.

Put simply, using this case as an example, if you define the background-color of the body and of :focus eligible elements (which, in IE9, is most things), then you must put the background-color value in your .css file.

This makes no sense, as anything in style tags in your .html file, defined AFTER the .css file, should take precedence. But it doesn't here. In fact you can define you :focus values AFTER you've defined your body values within either the .css file, or in style tags in the .html file, and it'll respect the values of the physical element over the :focus values every time. It's an entirely inconsistent practice.

Check out these link to see the same type of action occurring (you need to use IE9 or IE8, obviously):

:focus and body background-color defined in .css file

:focus defined in style tags in .html file, body background-color defined in .css file

:focus defined in .css file, body background-color defined in style tags in .html file

:focus and body background-color defined in style tags in .html file

You'll see that the first two links are green, while the second two are red. The first two are as we would expect it to work as we designed it, but actually probably work counter-intuitively to how priority is given to CSS values. The last two links display contrary to how we would like, but probably follow the rules properly

So... what should you do in this situation?

First of all, define your :focus with more specific scope. You probably don't care about focusing on your divs, so why not use "a:focus, input:focus"?

If this isn't an option, the only way to deal with this is to exploit the way IE9 interprets the priority of css values, and to use classes to define the background-colour that should be used, or to put specific inline styles on to your elements.

Class added to body (with body.class in .css file)

in-line style added to body

Conclusion?

When dealing with :focus for Internet Explorer, be careful, and be specific! If you can't be specific, then the next best thing is to get all of your themes and styles in to a .css file, again being more specific with your selectors than using the class as a simple object variable, and to ensure that where your pages need different styles to use those classes, not to try and use styling through <style> tags!