IE は runtimeStyle より !important のほうが強い

IECSS で !important が指定されていると、runtimeStyle が機能しなくなります。

デモ

IE6〜IE8 では、赤い "this is test" が表示され、その他のブラウザでは青く表示されます。

<html><head><title></title>
<style>body { color: red !important }</style>
</head><body>this is test
<script>
window.onload = function() {
  if (document.uniqueID) {
    document.body.runtimeStyle.color = "blue";
    alert(document.body.currentStyle.color); // red
  } else {
    document.body.style.setProperty("color", "blue", "important");
  }
};
</script></body></html>

つまりどういうこと?

私は、!important よりも、runtimeStyle が優先されるものだと思っていましたが、それは思い込みだったようです。

  1. CSS に !important が書かれていると、JavaScript レベルでスタイルをオーバーライドできなくなる。
  2. CSSそのものに手を入れようとしても(CSSパーサーの日記参照)、document.styleSheets.rules にアクセスした瞬間、元の CSS は改悪され手出しできなくなる。

静的に指定された !important が、動的に指定された runtimeStyle よりも優先されるってのは、致命的です。js から何もできなくなってしまいますから。

本当に方法が無いの?

方法はあります。
スタイルシートを追加し !important なルールを後から追加するのです。これでルールを上書できます。

IE6, IE7 で以下のコードを実行すると、メッセージボックスが表示されている間は、緑の "this is test" が表示されます。

<html><head><title></title>
<style>body { color: red !important }</style>
</head><body>this is test
<script>
window.onload = function() {
  if (document.uniqueID) {
    document.body.runtimeStyle.color = "blue";
    alert(document.body.currentStyle.color); // red

    var _sheet = document.createStyleSheet();
    _sheet.addRule("body", "color:green !important; font-size: 20pt");

    alert(document.body.currentStyle.color); // green

    _sheet.removeRule(_sheet.rules.length - 1);
  } else {
    document.body.style.setProperty("color", "blue", "important");
  }
};
</script></body></html>

IE8 は?

メッセージボックスを表示するタイミングによって、文字が赤いままだったりしますが、ルールを削除しない場合はちゃんと適用されているので、大丈夫のようです。

    alert(document.body.currentStyle.color); // green
//  _sheet.removeRule(_sheet.rules.length - 1);

IE8は、モーダルダイアログを表示していても、裏が最新の状態に更新される訳では無いようなので、スクリーンショットを取る場合は気をつけたいですね。