http://stilbuero.de Klaus Hartl – Stilbüro - Klaus Hartl


Jump to: Search, Additional Information.


whatever:hover, fast and easy

A way to easily implement whatever:hover in your IE/Win specific style sheet (you know, you should use Conditional Comments) is using Dynamic Properties.

Have a look at the following snippet:

.whatever {
    background-color: expression('#808080',
        this.onmouseover = function() { this.runtimeStyle.backgroundColor = '#eaeaea'; },
        this.onmouseout = function() { this.runtimeStyle.backgroundColor = '#808080'; });
}

It looks a bit odd, but it works! Here is a little demo page.

I like this solution a lot, because using htc-files always ended up in a hassle for me. And I like beating IE with his own weapons.

Update: It is of course better to avoid having to define the same styles in two different style sheets. One should use a class and just change the class attribute on mousover/mouseout. Here is an complete example (taken from the demo page) – first the CSS for all browsers:

.whatever {
    background: #808080;
}
.whatever:hover, .whateverhover {
    background: #eaeaea;
}

IE's extra CSS:

.whatever {
    background-color: expression(this.runtimeStyle.backgroundColor,
        this.onmouseover = function() { this.className += ' whateverhover'; },
        this.onmouseout = function() { this.className = this.className.replace('whateverhover', ''); });
}

Update: I got a tip at the css-discuss mailing list, that one can even leave out the first part of the expression – this.runtimeStyle.backgroundColor:

.whatever {
    background-color: expression(
        this.onmouseover = function() { this.className += ' whateverhover'; },
        this.onmouseout = function() { this.className = this.className.replace('whateverhover', ''); });
}

Thanks Brett!

Update: I got another hint from the css-d mailing list: The described technique fails in IE 5/Win, probably because of the braces { } inside the declaration.

Fortunately there is another way to create an anonymous function in JavaScript:

var myFunction = new Function([param1[, param2[,...paramN]]], "statement1[; ...statementN;"]);

That way, whatever:hover – fast and easy – works in that old browser as well:

.whatever {
    background-color: expression(
        this.onmouseover = new Function("this.className += ' whateverhover';"),
        this.onmouseout = new Function("this.className = this.className.replace('whateverhover', '');")
    );
}

One last thing to mention: The technique does not work in IE/Mac. That browser simply does not support Dynamic Properties.

20 Comments

Comments feed

  1. Nice technique!
    However I found it a bit slow when using a large xml table. Good for general purposes, but maybe not for a large table.

    Comment by Anonymous, November 11th, 2005 at 1:44 pm

  2. Author Comment

    Note: Wordpress adds an extra backslash for the quotation marks in the last snippet, therefore it won’t work if you copy and paste the whole thing.

    Instead of:

    new Function(\"this.className...

    it must read:

    new Function("this.className...

    Comment by Klaus, February 17th, 2006 at 6:22 pm

  3. Author Comment

    I just fixed the backslash quirk.

    Comment by Klaus, February 18th, 2006 at 11:53 pm

  4. Look at http://www.janbrasna.com/clanky/ie-hover-take-pro-ie5/
    In IE old, work your expression slowly bercause repeating adding JS, repeating +=classname… You create
    class=”aaa hover hover hover hover” if you moving on element

    Try this
    element {top:expression(
    isNaN(this.js)?(this.js=1,
    this.onmouseover=new Function(”this.className=’hover’”),
    this.onmouseout =new Function(”this.className=””)
    ):0);}

    Comment by peter, May 28th, 2006 at 12:46 pm

  5. Author Comment

    Hi Peter,

    thanks for the hint. Too bad I don’t speak Czech. I really don’t know, why it would result in class="aaa hover hover", because the added class is removed on mouseout.

    You can verify this by clicking into the paragraph in the test page.

    Maybe it is slowing down because there’s a function attached everytime the CSS gets reloaded (and IE does that quite often). Or maybe this is caused by a memory leak. I will have to check that.

    Comment by Klaus, June 5th, 2006 at 5:40 pm

  6. The original expression was so slow because every expression is evaluated repeatedly whenever you move your mouse over the element (or resize the window, etc.). Internet Explorer has to reevaluate this expression when any change occurs, because the expression could result in different value.

    Expression written by Peter sets property of the element (this.js=1) when it evaluates first time. In next evaluations it checks for isNaN(this.js), thus avoiding creating and attaching new functions when expression reevaluates.

    Comment by los, June 16th, 2006 at 11:20 pm

  7. Even better and easier way to handle multiple expression evaluation is to set the property with expression to null after the evaluation. It is faster than the previous one, because in this case the expression is evaluated truly only once. In the example below I chose the property “behavior” as it is IE-only just like expression itself:

    li
    {
    behavior: expression(
    this.onmouseover=new Function("this.className+=' hover'"),
    this.onmouseout=new Function("this.className=this.className.replace(' hover','')"),
    this.style.behavior=null
    );
    }

    Comment by los, June 28th, 2006 at 9:20 am

  8. Author Comment

    Los, thank you, this is very neat. I have updated the demo page.

    Comment by Klaus, June 28th, 2006 at 11:44 pm

  9. This is great, so much easier than anything else I’ve found. I was wondering how one would go about using this with background images instead of color? Any help would be appreciated! Thanks!

    Comment by Cameling, September 13th, 2006 at 1:55 am

  10. Author Comment

    Cameling, no problem at all, you can specify whatever CSS property you want for your classes. Here’s an example for a background image, that is not repeated and aligned in the upper left corner:

    .whatever:hover, .whateverhover {
    background: #eaeaea url(/path/to/your/image.png) no-repeat left top;
    }

    The image will be on top of the color, which acts as a fallback in case the image may not load.

    Comment by Klaus, September 13th, 2006 at 8:03 am

  11. And this works on a table cell hover? I’m sorry.. I’m not quite getting it.

    Comment by Cameling, September 14th, 2006 at 8:22 pm

  12. Author Comment

    Yes it should (although I haven’t tested it):

    Standards CSS:
    td:hover, td.hover {
    background: #eaeaea url(/path/to/your/image.png) no-repeat left top;
    }

    IE extra:
    td {
    behavior: expression(
    this.onmouseover = new Function("this.className += ' hover'"),
    this.onmouseout = new Function("this.className = this.className.replace(' hover', '')"),
    this.style.behavior=null
    );
    }

    Comment by Klaus, September 15th, 2006 at 8:31 pm

  13. I tried out this code and it failed to work in IE 6.0 , should this technique work for IE 6? Please see below :

    tr.agent_note_heading {
    background: #eaeaea;

    }

    tr.agent_note_heading:hover, .whateverhover {
    background: #808080;
    }

    tr.agent_note_heading {
    behavior: expression(
    this.onmouseover = new Function(”this.className += ‘ whateverhover’;”),
    this.onmouseout = new Function(”this.className = this.className.replace(’whateverhover’, ”);”),
    this.style.behavior = null
    );
    }

    Comment by lkehoe, November 13th, 2006 at 5:55 pm

  14. This is the corresponding html template
    “); return false;’
    width=100%>

    Comment by lkehoe, November 13th, 2006 at 6:00 pm

  15. Author Comment

    Yes, this technique does work in IE 6, simply visit the demo with IE and test it.

    What is going wrong in your code is that: You declared a background for the selector tr.agent_note_heading, and for the hover background you declared just a class without a type selector: .whateverhover. Thus the first one has a higher specificity and will be applied.

    Change your selector to tr.whateverhover to let them have equal specificity and make sure this one succeeds the other one in your style sheet.

    More on selector specificity.

    Comment by Klaus, November 13th, 2006 at 9:44 pm

  16. Thank you for the response. It did work.
    Here is the code in case others may benefit from the example:

    tr.agent_note_heading {
    border: 1px solid #000;
    padding: 2px;
    m: expression(this.onmouseover = new Function(”this.className = ‘agent_note_heading-hover’;”));
    font-family: verdana,lucida grande, sans-serif;
    font-size: 11px;
    }

    tr.agent_note_heading:hover,
    tr.agent_note_heading-hover {
    color: black;
    font-family: verdana,lucida grande, sans-serif;
    font-size: 11px;

    background-color: #c4e3f8;
    font-weight: bold;
    m: expression(this.onmouseout = new Function(”this.className = ‘agent_note_heading’;”));
    }

    Comment by lkehoe, November 14th, 2006 at 9:21 pm

  17. Author Comment

    Hm, I see a lot of redundant code there and an invalid property that shouldn’t be served to browsers other than IE

    Comment by Klaus, November 15th, 2006 at 8:43 am

  18. But its not working in IE 6.0. Is it possible for u to give the code which will support ie 6.0 :-)

    Comment by uni, March 19th, 2008 at 10:06 am

  19. Author Comment

    The whole thing was developed for IE 6, because in IE 7 you don’t need it anyway. And the demo works perfectly for me.

    Comment by Klaus, March 19th, 2008 at 10:47 am

  20. Thank you so much, I was able to make drop down menus work in IE 6 with this lovely trick. I too do not like to use htc files as the cause problems on php sites and for some reason aol’s browser from time to time.

    You have a very nicely laid out example. Many others drop hints, but you show it all.

    Peace

    Comment by Pathfinder, March 29th, 2008 at 7:21 am



Klaus Hartl – Stilbüro is powered by WordPress, jQuery, XHTML, CSS and me.