javascriptcssinternet-explorerinheritancecss-expressions

Can !important rules be used in IE's CSS expressions?


Firstly, I know that CSS expressions are defunct and wrong in so many ways, and also to avoid using !important where possible. This is for a special case stylesheet.

In Short

My question is... Is there any way for a CSS expression to set the !important flag?

E.g. this doesn't work:

a { color:expression('red !important'); }

[Edit: thanks to MarmaladeToday's comment below]. This also doesn't work:

a { color:expression('red') !important; }

Can this be done some other way?


In Detail

What I'm actually trying to do is mimic the inherit value in IE6 & 7. This works:

color:expression(
    this.parentNode.currentStyle ?
        this.parentNode.currentStyle.color: 'red'
    );

But I also want to set the !important flag, and this doesn't work:

color:expression(
  (
    this.parentNode.currentStyle ?
        this.parentNode.currentStyle.color: 'red'
  ) + ' !important');

I'm aware that, in JavaScript, it isn't possible to set !important via an element's style object. E.g. this won't work:

element.style.color = 'red !important';

However, it is possible to set !important via the element's style attribute:

element.setAttribute('style', 'color:red !important;');

So... are CSS expressions limited to interacting with the style object, and therefore, what I want to achieve is impossible - or is there any way for an expression to affect an element's attributes, or pass !important in some other way?


Starting a Bounty

No solid answers so far, so I'm starting a bounty.

Ideally, I'm looking for a CSS-based solution for mimicking inherit !important in IE6 and IE7, either with or without CSS expressions. (Please do verify that your suggestions work before posting).

At least, a link to some authoritative reference telling me that this is impossible would mean I could lay this train of thought to rest - I've not seen anything mentioning the use of CSS expressions with the !important rule.


Solution

  • The reason those CSS expressions don't work is because IE only evaluates the expression for the last property in the cascade.

    E.g. if you have an HTML document with a link inside it and the following "CSS",

    a {
        color: expression(function(e){
            alert('success');
            e.runtimeStyle.color = 'blue';
        }(this));
    }
    a { color: red; }
    

    you will never see that alert (nevermind the style change), because the CSS expression is never evaluated. So no, you can't use an expression to set the !important flag.

    That is to say, not when you try to set it on the same property. You can cheat. But that does make the expression a bit more complicated:

    a {
        filter: expression(function(e){
            e.runtimeStyle.color = 'blue';
            alert('success');
            e.style.filter = '';
        }(this));
    }
    a { color: red; }
    

    There are a few things to note here.

    If you simply use another CSS property, you can be sure that the expression will be evaluated. Or at least, a little more sure, because if there's another rule further down the cascade that uses the same property already, you're still out of luck.

    Secondly, you have to use runtimeStyle instead of currentStyle. If you used currentStyle here, the second rule would still end up overwriting it. runtimeStyle overrides all other CSS (except !important declarations). So it's the JScript equivalent of !important.

    Also note that I'm resetting the filter property itself as well. That prevents the expression from being continuously re-evaluated. But as much as that may reduce performance, I don't think it's super critical. The main reason I put it in here is because I added alert()s in those expressions, and you definitely don't want to have those pop up forever.

    It is in fact also possible to use any other property you make up. This works too:

    a {
        bogus: expression(function(e){
            e.runtimeStyle.color = 'blue';
        }(this));
    }
    

    However, since the bogus property doesn't actually exist, you can't reset it using Javascript, so this will be re-evaluated continuously.