Thoughts on life, liberty, and information technology

An IE6-compatible solution for :hover

Something I like to incorporate on web sites with tables is automatic background highlighting of the row that the mouse is hovering over. This is easy to do with CSS:

table.hover tr:hover
{
background-color:#ffffcc;
}

All you need to do is give your table tag the hover class, and your mouseover hover background color works!

In all browsers except IE6, of course. IE6 only supports the :hover pseudo-class on anchor () tags. (There’s lots of other things that IE doesn’t support or supports wrong, but that’s a story for another day.)

How can we get IE6 to hover our table rows? By using a little JavaScript and the Prototype library. Our solution requires two steps:

  1. Write some code to automatically detect mouseover and mouseout events on table rows, applying and removing a CSS class to the rows as the events occur.
  2. Add the CSS class to our CSS file.

First we’ll add a tr.hover declaration to our CSS.

table.hover tr:hover, table.hover tr.hover
{
background-color:#ffffcc;
}

Notice that I kept the table.hover parent selector; this is important, as we’ll use that to ensure we only apply our hover code to table rows in tables that have the hover class.1

To get the class added (and removed) from our table rows, we use Prototype to find all elements that match the CSS selector table.hover tr, and for each one, hook a function to the onmouseover and onmouseout properties.

$$('table.hover tr').each( function(e) {
e.onmouseover += function() {
Element.addClassName(e, 'hover');
};
e.onmouseout += function() {
Element.removeClassName(e, 'hover');
}
});

Problem #1: The code above is applied to all browsers. We only need it applied to versions of IE prior to 6.0. A simple hack for this was found at Ajaxian, and is added below.

if (!window.XMLHttpRequest)
{
$$('table.hover tr').each( function(e) {
e.onmouseover += function()
{
Element.addClassName(e, 'hover');
};
e.onmouseout += function()
{
Element.removeClassName(e, 'hover');
}
});
}

Problem #2: What if our event model already declared an event on the onmouseover or onmouseout properties? The script above would clear any existing event handlers. The solution is to use Prototype’s Event.observe method to hook the functions.

if (!window.XMLHttpRequest)
{
$$('table.hover tr').each( function(e) {
Event.observe(e, 'mouseover', function() {
Element.addClassName(e, 'hover');
});
Event.observe(e, 'mouseout', function() {
Element.removeClassName(e, 'hover');
});
});
}

Problem #3: If the JavaScript runs before the page loads, it may not apply the event handlers to our table. This is also resolved by using Event.observe to run the above code only after the window loads.

if (!window.XMLHttpRequest)
{
Event.observe(window, 'load', function() {
$$('table.hover tr').each( function(e) {
Event.observe(e, 'mouseover', function() {
Element.addClassName(e, 'hover');
});
Event.observe(e, 'mouseout', function() {
Element.removeClassName(e, 'hover');
});
)};
)};
}

There you have it — a :hover hack for IE6 that doesn’t break IE7 or Firefox. It should work with all other modern browsers, though some old browsers may have issues with it. If you know of any browsers which break with this solution, let me know.


1 The use of the class name hover caused a problem when including YUI’s Button CSS code. In their CSS, they have a CSS selector for .yuibutton.hover. Apparently, IE6’s issue with these selectors caused my entire table to pick up the CSS from .yuibutton.hover. To fix this, I renamed YUI’s CSS selector to .yuibutton.yuihover and updated their JavaScript (just search/replace 'hover' with 'yuihover').

25 responses to “An IE6-compatible solution for :hover”

  1. Conficio Avatar
    Conficio

    Cool feature and certainly a cool solution. I’m becoming a fan of your blog 😉

    K<o>
    Busy, providing technical support to non technical users of OpenOffice,org

    Like

  2. kangax Avatar
    kangax

    Just a bit simplified version…

    Event.observe(window, ‘load’, function() {

    if (Prototype.Browser.IE)

    {

    $$(‘table.hover tr’).each( function(el) {

    el.observe(‘mouseover’, function(e) {

    Event.element(e).addClassName(‘hover’);

    });

    el.observe(‘mouseout’, function(e) {

    Event.element(e).removeClassName(‘hover’);

    });

    });

    }

    });

    Like

  3. brian Avatar
    brian

    I didn’t realize Prototype had a Browser object. Good tip on that, and on using the extended element classes instead of calling Element methods.

    Like

  4. Scott Avatar
    Scott

    Can anyone provide a simple working version of this work around?
    I can not seem to get the page to work.

    Thanks in advance.

    Like

  5. brian Avatar
    brian

    Add class=”hover” to your table tag. Without this, the script won’t do anything. The “hover” behavior is applied only to those tables with the “hover” class.
    Add a tr.hover declaration that does something to your CSS (such as “background-color:grey”). The tr.hover declaration in your CSS should reflect the style you want to apply when hovering over your table rows.
    Reference the Prototype library from your HTML file (script src=”…”). This is a core dependency.

    Like

  6. Mark Perkins Avatar
    Mark Perkins

    Nice solution… but only if you are using prototype for some heavy lifting javascripting on your site anyway. Not sure if 40K of javascript is really worth it for just a bit of table striping.

    Just give ie6 users a slightly degraded browsing experience – that way they may slowly realise that changing browsers is actually worthwhile and we may eventually be rid of these issues.

    Like

  7. brian Avatar
    brian

    I agree that using Prototype just for hovering support in IE6 is not worth it — unless that hovering support is critical otherwise (which is doubtful). Then again, if you’re already using Prototype (which I usually am)… 🙂

    As well, the same techniques can be done with any JS library — or none (plain ‘old JS).

    Like

  8. Livingston Samuel Avatar
    Livingston Samuel

    the simple solution that will fix the hover issue in Internet Explorer 6

    http://blog.delivi.info/javascript/hover-for-non-anchor-elements-in-ie6/

    Like

  9. Femi Avatar
    Femi

    For me onmouseout events are not working if I using span tag

    Like

  10. chrisff Avatar
    chrisff

    why not do the browser test before adding the event?

    Like

  11. brian Avatar
    brian

    Um, good point. 😉

    Like

  12. Daisy Avatar
    Daisy

    Hey guys,My name is Daisy and I’m new to web programming. I’m having this problem with IE6. My client really wants that the color of the table change when someone put the mouse over it, even in IE6 (he says it is the browser the most of his clients use) Well I’ll used the code the guy suggested between the tags in the beggining of my html code. But I really don’t know how to apply it to my table (wich is very partitioned with some php code and mysql applies inside it. if someone can help, i would be grateful ^_^

    the script

    Event.observe(window, ‘load’, function() {
    if (Prototype.Browser.IE)
    {
    $$(’table.hover tr’).each( function(el) {
    el.observe(’mouseover’, function(e) {
    Event.element(e).addClassName(’hover’);
    });
    el.observe(’mouseout’, function(e) {
    Event.element(e).removeClassName(’hover’);
    });
    });
    }
    });

    the table

    echo "";

        while ($aux1 = mysql_fetch_array($res1)){
    

    $cor = $aux1['d_nome'];

    $combustivel = $aux1['cm_nome'];

    if ($aux1['f_fotos'])

    //verifica a existencia de fotos no cadastro

    $auxFoto = $aux1['c_idcarro'];
    $queryAuxFoto = mysql_query("select count(id_foto) as count from fotos where id_carro = $auxFoto");
    $nrAuxFoto = mysql_fetch_array($queryAuxFoto);

    if($nrAuxFoto['count']){
    $queryFoto = mysql_query("select foto from fotos where id_carro = $auxFoto group by id_carro order by foto asc");
    $dadosFoto = mysql_fetch_array($queryFoto);

    //while ($dadosFotos['foto'] = $queryFoto)
    $srcFoto = str_replace("fotos/", "fotos/t", $dadosFoto['foto']);
    
    $foto = "http://www.meuautonovo.com.br/".$srcFoto;
    

    } else {
    $foto = "imagens/estoque/vazio.gif";
    }
    echo ...

    ";
    

    Like

  13. brian Avatar
    brian

    @Daisy,

    You seem to have added the JavaScript properly. Two things to check:

    1) Are you also including the Prototype javascript library (http://www.prototypejs.org/)?

    2) Are you adding the CSS class “hover” to your table (as in <table class=”hover”>)?

    Like

  14. Christine Avatar
    Christine

    Thanks for this function. I needed to exclude the first tr in the table as it contained headers. I thought I’d post the code in case it would help anyone else.

    Event.observe(window, 'load', function() {
        if (Prototype.Browser.IE) {
            var f=$$('table.hover tr');
            f.shift();
            f.each( function(e) {  
                Event.observe(e, 'mouseover', function() {  
                    Element.addClassName(e, 'hover');  
                });  
                Event.observe(e, 'mouseout', function() {  
                    Element.removeClassName(e, 'hover');  
                });  
            });  
        }
     });
    

    Like

  15. brian Avatar
    brian

    Thanks for sharing the code, Christine!

    Like

  16. mukesh Avatar
    mukesh

    Hi!

    how will I use this code to my html page please suggest me. I am just a beginer to javascript. So where this css and this javasript will be used and how please suggest me with example.

    Thanks!

    Like

  17. brian Avatar
    brian

    Simply put…

    Include the CSS code as shown at the top of the blog post (in your existing CSS file).

    Include the Prototype JavaScript library in your HTML page (www.prototypejs.org) (typically in the HTML header).

    Include the JavaScript as shown in the blog post (under “Problem #3”) at the bottom of your HTML page.

    If you don’t know how to incorporate CSS or JavaScript into an HTML page, I’d suggest you research those first before trying to implement the code in this blog post.

    Like

  18. Nicusor Avatar
    Nicusor

    On the last piece of code (#3) you put the last ) in the wrong place… it should be on the previous row.

    Like

  19. brian Avatar
    brian

    Thanks — fixed!

    Like

  20. Relatively Fixed » The Ultimate List of IE6 Hacks, Fixes, & Resources

    […] An IE6 Compatible Solution for :hover […]

    Like

  21. Livingston Samuel Avatar
    Livingston Samuel

    An optimized solution for this problem using jQuery can be found at http://blog.delivi.com/javascript/updated-hover-for-non-anchor-elements-in-ie6/

    Like

  22. The Ultimate List of IE6 Fixes & Hacks « blog.mattsparks.com

    […] An IE6 Compatible Solution for :hover […]

    Like

  23. poupougnac Avatar
    poupougnac

    If you’re using jQuery, this is a plugin that just purely implement the pseudo class :hover on ie6 for every elements. It works exactly like any other browser and you don’t need to change your code. Just loading the plugin. For me the best and fastest solution.
    http://plugins.jquery.com/project/ie6hover

    Like

  24. The Ultimate List of IE6 Fixes & Hacks | Matt Sparks Blog

    […] An IE6 Compatible Solution for :hover […]

    Like

  25. Yang Suck Lee Avatar
    Yang Suck Lee

    Hello
    Code you have been inspired.
    But while you apply the code, you have made my own jquery code.

    ===================================================================

    $(document).ready(function (){

    $("table.t1 tbody tr").each(function(){
    
        $(this).hover(function(){
            $(this).addClass('hover');
        },function(){
           $(this).removeClass('hover');
        });
    
    });
    

    });

    Like

Leave a reply to Yang Suck Lee Cancel reply