:hover in IE7…. sucks….

As this is a somewhat relevant topic with respect to the kinds of things I would like to talk about here, I’m copying this post over from my now defunct blog over at blogspot.com….

I had some interesting findings while trying to figure out why mouse-event-based hover behaviors were so slow in IE7 for a DHTML web application on a major website that uses mouseover/mouseout events to change the background color of a table row. All other browsers (including IE6) did this lightning fast, even with very large tables. However, IE7 sucked major ass, even when tables were only 20 to 30 rows. (also note that for optimal performance in IE do this by changing the inline style backgroundColor property explicitly vs. swapping out style classes. That was another lesson learned on another day) …anyway

So one of the first things I tried was to remove all javascript and CSS payload from the page (stripped down to bare markup), and added just enough javascript back in to handle the row highlighting on mouseover/mouseout. When I did this suddenly the row highlighting was rocket fast again! So I added the CSS back into the payload. Slow. Aha!! Frak!! Now what? Then I started a process of pulling the CSS back-in in bite-size chunks to see what CSS might be causing the slow down. This took several hours as the site has a very large CSS payload, but once I figured out the pattern this started to go much faster. Turns out any selectors in the payload that had “:hover” psuedo-classes that weren’t specifically targeting anchor tags, slowed down mouse events for IE7 (in standards mode only). This was even for selectors that would end up not selecting anything in the DOM because they were scoped in such a way as to only be pertinent to non-IE browsers. And it only took 1 selector to slow down the page. Every single one had to be removed before it sped back up to normal performance.

So in summary, when pushing alot of CSS payload into a document, and you see sucky performance in IE7 mouseover/mouseout event speed, make sure your CSS payload
is GOOD, and not BAD . . .

BAD BAD BAD (not explicitly targeted to anchor)

    :hover { . . . }
    .foo:hover { . . . }
    #foo:hover { . . . }
    div.foo:hover { . . . }

GOOD (explicitly targeted to anchor)

    A:hover { . . . }
    A.foo:hover { . . . }
    A#foo:hover { . . . }

Good luck, hope this helps someone. God I hate IE.

Advertisements

9 Comments

  1. Posted February 17, 2009 at 12:35 am | Permalink

    You, my friend, are absolutely awesome. We have probably send a good three days rewriting a lot of our Javascript, debugging, only to finally come to the same conclusion as you did here. The moment I figured out it was related to and assumed it was something that would only appear in IE7 (due to lack of non-a:hover support in IE6) I found your article.

    In our case, the slow down occured in a relatively heavy Google Maps application that has some large collections of our own overlays, polygons and markers included.

    It is very much worth noting that it seems as if the target of the CSS rules is irrelevant for the slow down. We immediately started noticing performance gains when removing CSS rules that were writting using a non-explicit A element (though applied to them) but wouldn’t even match in the document! Going back into the stylesheet and rewriting all :hover lines like this did a lot for us.

    I am spreading the word around. Many of my colleagues and friends never heard of this bug before. Thanks.

  2. jdarren
    Posted February 17, 2009 at 2:36 pm | Permalink

    I was quite surprised by my own findings. . . Glad to hear that someone benefited from this posting!

  3. Posted February 19, 2009 at 4:54 pm | Permalink

    We were having the exact same problem. I had suspected it was a CSS issue, but had no idea it was this obscure. Thanks for pinpointing the issue!

  4. Hal
    Posted March 24, 2009 at 7:24 am | Permalink

    Thanks for your post.
    I’m struggling with the same problem.
    I just wonder how you solved this in your DHTML-markup? Where do I put the anchor tag in the table? Could you give an example?

    Cheers!

  5. jdarren
    Posted March 25, 2009 at 11:43 pm | Permalink

    Hello Hal,
    The placement of anchors whether in a table or other structure wasn’t really relevant to the issue. The issue was :hover selectors in the CSS payload that aren’t explicitly scoped to the anchor element (e.g. .foo:hover vs. a.foo:hover) And if you need hover behavior on elements other than anchors, i would suggest using javascript in IE7.

    Cheers

  6. Ignac Vucko
    Posted June 26, 2009 at 9:10 am | Permalink

    Thanks for the article.

    Just encountered this same issue when using hover on a div.
    To resolve, I used onmouseenter/leave for IE, which is ignored by other browsers.
    I suppose wrapping the div in an anchor tag and having the hover effect on the anchor tab might solve it as well…though i didn’t try that.

  7. vitalic
    Posted October 29, 2009 at 2:56 am | Permalink

    this blog post just saved countless hours of pain staking trial and error

    you sir, win an internet

  8. Posted October 29, 2009 at 6:38 am | Permalink

    This just helped out the guys working on the beta BBC homepage – kudos!

  9. Mark
    Posted December 23, 2010 at 4:42 am | Permalink

    The same applies if the selector contains any child selectors:

    html > body a:hover { /* BAD */ }
    html body a:hover { /* GOOD */ }

    I suspect IE has special code for anchors, but anything that breaks this optimisation (such as an unqualified :hover in standards mode) means a full DOM traversal.

    Under a debugger it’s spends a lot of time here:

    mshtml!CTreeNode::GetFancyFormat+0x35
    mshtml!CElement::UpdateFormats+0x2c5
    mshtml!CElement::HandleMouseHoverForStyle+0x22f

    Which of course is recursive.

    Cheers,
    Mark


Post a Comment

Required fields are marked *

*
*

%d bloggers like this: