動的に生成したノードに対する currentStyle と getComputedStyle はいつから利用できるか?

IE6, IE7, IE8 では node.currentStyle を使うことで計算済みのスタイル情報にアクセスできます。また、IE9を含むその他のブラウザでは、window.getComputedStyle(node, "") を使うことでアクセスできます。

getComputedStyle では、単位系が px に統一されていますが *1、currentStyle では単位系は統一されず "3em" や "auto" などやる気がない値が取れてくるので注意が必要だったりします。

実際どうなのか調べました

HTMLに静的に埋め込んだノードは、計算済みのスタイルをいつでも取得できますが、動的に生成したノードはどうなっているのでしょうか?
IE7, IE8, IE9pp7, Firefox4.0β7, Firefox3.6.13, Opera10.63, Safari5, Google Chrome 9 dev で調べてみました。

結果

  • DOMツリーに参加していないノード(node.parenNode = null)は、計算済みのスタイルを取得できない
  • Gecko は例外で、parentNodeの状態に関わらずいつでも取得できる
  • IE9pp7 の結果が予想と異なる

ということがわかりました。

おわり。

<!DOCTYPE html><html lang="ja"><head><meta charset="utf-8" />
<title></title>
<style>
#id1 {
    position: absolute;
    top: 200px;
    left: 200px;
    width: 100px;
    height: 100px;
    filter: alpha(opacity=50);
    opacity: 0.5;
    background: gray;
}
</style>
<script>
window.onload = function() {
    var node = document.createElement("div");

    node.id = "id1";

debugger;
    // PHASE1. DOMツリーに参加していない状態で計算済みのスタイルを取得する
    //
    // node は作りたてで、まだDOMツリーに参加していない状態
    // この状態では、各ブラウザがバラバラの挙動になる
    //
    // IE6, IE7, IE8 - ""   (node.currentNode が null になる)
    // WebKit        - ""   (取得できない)
    // Opera         - ""   (取得できない)
    // Gecko         - 0.5  (取得できる)
    // IE9pp7        - 1    (他のブラウザとも、予想とも異なる)
    if (window.getComputedStyle) {
        alert("PHASE1:" + window.getComputedStyle(node, "").opacity);
    } else {
        var currentStyle = node.currentStyle || { filter: ""};
        alert("PHASE1:" + currentStyle.filter);
    }

    // PHASE2. DOMツリーに参加後に計算済みのスタイルを取得する
    //
    // DOMツリーに参加させると、計算済みのスタイルが取得可能に
    // IE6, IE7, IE8 - "alpha(opacity=50)"
    // WebKit        - "0.5"
    // Opera         - "0.5"
    // Gecko         - "0.5"
    // IE9pp7        - "0.5"
    document.body.appendChild(node);

    if (window.getComputedStyle) {
        alert("PHASE2:" + window.getComputedStyle(node, "").opacity);
    } else {
        var currentStyle = node.currentStyle || { filter: ""};
        alert("PHASE2:" + currentStyle.filter);
    }

    // PHASE3. DOMツリーから再び切り離した状態で計算済みのスタイルを取得する
    //
    // IE6, IE7, IE8 - ""   (node.currentNode が null になる)
    // WebKit        - ""   (取得できない)
    // Opera         - ""   (取得できない)
    // Gecko         - 0.5  (取得できる)
    // IE9pp7        - 1    (他のブラウザとも、予想とも異なる)
    document.body.removeChild(node);

    if (window.getComputedStyle) {
        alert("PHASE3:" + window.getComputedStyle(node, "").opacity);
    } else {
        var currentStyle = node.currentStyle || { filter: ""};
        alert("PHASE3:" + currentStyle.filter);
    }

    // PHASE4. DocumentFragmentに入れた状態で計算済みのスタイルを取得する
    //
    // IE6, IE7, IE8 - ""   (node.currentNode が null になる)
    // WebKit        - ""   (取得できない)
    // Opera         - ""   (取得できない)
    // Gecko         - 0.5  (取得できる)
    // IE9pp7        - 1    (他のブラウザとも、予想とも異なる)
    var df = document.createDocumentFragment();

    df.appendChild(node);

    if (window.getComputedStyle) {
        alert("PHASE4:" + window.getComputedStyle(node, "").opacity);
    } else {
        var currentStyle = node.currentStyle || { filter: ""};
        alert("PHASE4:" + currentStyle.filter);
    }

}
</script>
</head><body></body></html>

*1: 事実上統一されているだけで仕様上は実装依存