CSSだけでIEのjavascriptの有無を判定してスタイルを切り替える

追記
IE6でフリーズしました(>o<)。IE5.5とIE7・8(ie7モード)では動作。この辺りが目にしない理由でしょうか、、

追記2(05/02)
ActiveXの有効・無効とJavascriptの有効・無効は個別に設定できますが、以下ではjs無効ならActiveXも無効だろう(その逆も)という前提で書かれています。いろいろ察してお読みください。


CSSだけでIEのjavascriptの有無を知りたい、というケースがごくごく僅かですがあるかな、ということでご紹介です。

IEの8までは透過やドロップシャドウ、グラデーションといった効果を独自拡張のfilterプロパティで実現できて、他のモダンブラウザと近い表現ができます。

しかしこのプロパティはjavascriptが無効の場合は機能しません。(IETesterでは、javascriptを無効にしてもfilterは機能するみたいです)

また、IEにはcss expressionという独自拡張もあってCSSの未実装機能やバグの手当てに使われています。これもjavascriptが無効の場合は機能しません。(またIE8では同時期の他のブラウザに比べてCSSのサポート状況が貧弱にもかかわらず、標準準拠のIE8モードではcss expressionが無効です。このおかげでIE5.5よりたちが悪いときもあります、、、)

そこでjavascriptがoffのためfilterが使えない、css expressionが使えない場合に、スタイルを切り替えて対処する仕組みが必要になるかと思います。

スクリプトを使って(javascriptが有効の場合は)、bodyタグのクラス名に ieJsEnabledを追加する、なんてことをすれば、そのクラスの有無でスタイルを切り替えることができます。

またjavascriptを使わないでhtmlに以下のタグを書くことでもIEでjsが無効の場合のスタイルを書くことができます。
<noscript><!--[if lt IE 9]><div id="ieJsDisabled"><![endif]--></noscript>

みんなが幸せになるなにか

<noscript><!--[if lt IE 9]></div><![endif]--></noscript>


で、何かの都合で以上なテクニックが使えない、使いたくない場合、css内でjsの判定を行う方法です。

css expressionが動くということはjavascriptが有効なので、そのcss expression内で自身のclass名を書き換えます。css expressionはことあるごとにスクリプトの評価が起こってただでさえ遅いIEをますます不安定にしてしまうようですが、以下のような書き方の場合、最初の一回の評価以降はクラス名が書き換わって評価されないので大丈夫です。多分。また、同様にしてidも書き換えられます。
.ieJsDisabled {
 scrollbar-shadow-color: expression( this.className='ieJsEnabled');
}

もっと汎用的にしたいと、this.className = this.className.replace(/ieJsDisabled/i, 'ieJsEnabled')としてみましたが動きませんでした。css expression内では単純な代入しかできないみたいです。またthis.style.~な書き換えはできませんでした。

ついでにexpressionのダシに使うプロパティは、あまり影響の出なさそうなもの、ということでscrollbar-shadow-colorにしてみました。

一年ほど前からHTMLタグを発行するツールを制作して運用しています。当初はIEのjavascript無への配慮がなくてhtmlも切り分けができるように書かれていませんでした。しかし今回の方法で、cssを差し替えるだけでjavascript無にも対応できるようになりました。

以上はここ数日考えていて、昨日から検証して運用しています。もし導入される場合はぜひお手元で検証してから導入してください。