IEの独自CSS拡張-ms-filterとの正しいお付き合い

今更ですが...

Windows 版の IE4 から登場し CSS3 Opacity 等を先駆けて(不十分に)実現した IE 独自 filter (以下 独自 filter)について。重要そうな点について寡聞にしてズバリな言及を見なかったので書いておきます。

独自 filter の切り方

しばしば ActiveX を切っていると独自 filter は使えない、といわれます。

しかし詳しく見ていくと MSXML(ActiveX 版 XHR) などは使えるのに独自 filter は使えない、という状況も発生するようです。

独自 filter だけを切るには、インターネットオプションから画像のように“バイナリ ビヘイビアーとスクリプト ビヘイビア-”を無効にします。(Windows XP sp3, IE8 で確認)

安全な独自 filter 有効/無効の確認

独自 filter の判定には随分試行錯誤してしまいました。既に一般的な情報なら悪しからず...

// 1.
IE_FILTER_ENABLED = !!window.ActiveXObject;
// 2.
IE_FILTER_ENABLED = (function(t){
  try {t = new ActiveXObject('DXImageTransform.Microsoft.gradient');}
  catch(e){}
  return !!t;
})();

1. では実際に ActiveX が有効か?の判定はできないようです。

2. のように実際にオブジェクトを生成し戻り値を見ないと ActiveX や今回でいえば独自 filter が使えるか?判定できません。

しかし 2. の方法ではブラウザのセキュリティ設定によっては、スクリプトの実行に関するアラートが出てしまってユーザーを少なからず困惑させてしまいます。

安全な確認法

そこで僕の結論は、隠し要素を生成して DXImageTransform.Microsoft.Shadow を設定し要素のサイズを測って判定です。

ドロップシャドウが描画されれば、要素のサイズが影の分大きくなるので判断できるというわけです。

(function(){
var temponload = onload;

onload = function(e, d, b, c){
  if( temponload ) temponload(e);
  temponload = null;
  
  if( onload === arguments.callee ){
    onload = new Function();
    onload = null;
  };
  
  d = document;
  b = d.body;
  c = b.className || '';
  e = d.createElement('div');
  b.appendChild(e);
  e.style.cssText = 'position:absolute;top:0;left:0;width:1px;height:1px;line-height:1px;filter:dropshadow() progid:DXImageTransform.Microsoft.Shadow();';
  b.className += ( c ? ' ' : c ) + ( e.offsetHeight > 1 ? 'pbLCD-AX' : '' );
  e.style.cssText = '';
  b.removeChild(e);
}; 
})();

ちなみに line-height:1px は IE5.5 以下用の指定です。

また IE5 でも正しく判定できるように dropshadow() を併せて指定し、隠し要素の削除の前に filter スタイルの削除も行っています。filter の利いたまま要素の削除を行うと IE5 では不具合に見舞われます。また IE5 では elm.removeAttribute( 'style' ); が機能し無いため elm.style.cssText = ''; を使用します。