9

I've got a reference to a CSSStyleRule object in JavaScript and I want to update the style for border-top-color to red !important. If I assign the value red, no problems occur. If I assign the value red !important, the value is ignored (i.e. not assigned).

myStyleSheetRule.style.borderTopColor = 'red'; // success
myStyleSheetRule.style.borderTopColor = 'red !important'; // fail

How do I set the !important flag?

Note that it has to be done via a stylesheet rule accessed programatically. In my use case, I can't assign a style attribute or anything else. I'm using Chrome on Windows 7.

Nathan Ridley
  • 33,766
  • 35
  • 123
  • 197

3 Answers3

4

Something like this should work:

HTML

<div id="colored">?</div>​​​​​​​​​​​​​​​​​​​​​​​​​

Default stylesheet

#colored {
    border-top: 1px solid Black;
}​

Javascript

var all = document.styleSheets,
    s = all[all.length - 1],
    l = s.cssRules.length;

if (s.insertRule) {
    s.insertRule('#colored {border-top-color: Red !important}', l);
} else {
    //IE
    s.addRule('#colored', 'border-top-color: Red !important', -1);
}​
spliter
  • 12,321
  • 4
  • 33
  • 36
  • 1
    In this particular case you might even not need to add '!important' since the javascript above, appends the style to a stylesheet, means it has to override the earlier styles in the stylesheet. – spliter Jul 31 '12 at 07:38
  • So, essentially I'm guessing the only way to do it is kill off the old rule and add a new one. Directly setting the style property won't work. Regarding your comment, that won't do the trick as the order of styles doesn't help if a previous selector is a more specific match than the subsequent one. – Nathan Ridley Jul 31 '12 at 07:49
  • I don't understand why you need to kill off the old rule? You just "append" your rule to the stylesheet. No killing of anything. insertRule/addRule are not destroying anything, they just add your style declaration. I think for your particular case, the best thing would even be to create a new stylesheet programmatically to add all your plug-in's styles there. But then, probably, you need to consider creating normal stylesheet instead of adding rules in JS. – spliter Jul 31 '12 at 07:55
  • I have updated the JS snippet to make sure we append the style rules to the latest stylesheet if we have more than one – spliter Jul 31 '12 at 08:00
  • The rule has other styles in it as well, not just the one I mentioned. Also it's not a one time operation; the rule is being changed frequently and thus I can't just keep adding new rules all the time. I could remove the ones I already added of course... – Nathan Ridley Jul 31 '12 at 08:00
  • You mean you need to add other rules in your JS, or there are existing inline styles for this element defined in "style" attribute? If it's the first one, then there is no problem adding more styles like in the snippet above. If it's the second, then "!important" will override them anyway as long as "!important" is not defined inline as well. But then it turns into dirty evil. Anyway, I think the snippet answers your question of stylesheet rule accessing stylesheet rule programatically and setting the !important flag. – spliter Jul 31 '12 at 08:04
  • If it's a frequently changing operation, then you have to use 'style' attribute. But it was not clear from your question. – spliter Jul 31 '12 at 08:06
  • That's the point of the question - the style attribute doesn't appear to allow me to assign !important with the style value. – Nathan Ridley Jul 31 '12 at 08:44
  • @NathanRidley: Are you sure the element whose style is being changed is entirely visible and no part of it is covered by another element? i.e.: partially beneath another element with `position:absolute` style, or the element has a negative `margin` style. – Jay Jul 31 '12 at 23:36
  • @Jay - I'm setting property of a stylesheet rule, not an element style. – Nathan Ridley Aug 01 '12 at 03:54
  • @NathanRidley: Seems like there's a periodical or event based function that refreshes the stylesheets and strip the `!important`. The function could be refreshing the stylesheet by rebuilding the whole `innerHTML` from a style cache instead of updating the rules one by one. So when you change a rule, that function will replace it with the one from its cache. You may want to check it to change the style using a simple HTML and without any script library whatsoever. – Jay Aug 01 '12 at 05:43
  • No, I don't have any functions running like that. You can verify that what I'm saying is true by setting the two test values I've mentioned and seeing that the first value sets correctly, but the second one doesn't. – Nathan Ridley Aug 01 '12 at 07:49
0

This should make the trick;

var property='color';
var value='red !important'; 
var selector='h1';

if(value.indexOf("!important") > 0){
           var newRule=myStyleSheetRule.style.cssText+" "+property+":"+value;
           myStyleSheetRule.insertRule(selector + " { " + newRule + "; }",/*indexOfTheRule*/);            
           myStyleSheetRule.deleteRule(/*indexOfTheRule*/);
    }
Zortext
  • 566
  • 8
  • 21
-1

Try:

myStyleSheetRule.setAttribute('style', 'border-top-color:red !important');

This will add it inline.

Jory Cunningham
  • 744
  • 5
  • 6
  • 1
    why not just read the existing style attributes into the new style attributes then? Assuming they are there already just read them then concatenate them with 'border-top-color:red !important'. I don't think you can declare !important with JS styles, it has to be written inline or added as an embedded – Jory Cunningham Jul 31 '12 at 06:05
  • Seems like a messy way to do it but if nobody comes back with a better way I'll give it a go. Thanks. – Nathan Ridley Jul 31 '12 at 06:36
  • It is possible to add anything you want to the stylesheets programmatically if needed. Check out my answer – spliter Jul 31 '12 at 07:37