IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

getComputedStyle について調べてたら深みにハマったのでメモ

getComputedStyle とは!?

ある要素にどんなスタイルが当たっているかを計算してくれる。便利な関数。
使いかたはめっちゃ簡単!

var style = getComputedStyle(element, '');

alert(style.fontSize); // 14px
alert(style.color);    // rgb(0, 0, 0)

ちなみに第二引数は疑似要素の style を取りたい場合に使います。通常は空文字列でいい。

でも、 getComputedStyle はこのままでは IE, Safari では動かない。

Safari では

window(グローバル領域) に getComputedStyle は定義されてなくて、 document.defaultView だけに getComputedStyle が定義されている。
ちなみに、 Firefox, Opera では document.defaultView == window なので、以下のようにすることで Firefox, Opera, Safari で使うことができる。

var style = document.defaultView.getComputedStyle(element, '')

IE では

そもそも getComputedStyle という関数自体が存在しない
その代わり、 IE ではすべての HTMLElement が currentStyle というプロパティを持っていて、これが getComputedStyle で取得できるオブジェクトとほぼ同じ役割をする。
ということで、さっきの例は以下のようにすると IE にも対応できる。

var style = element.currentStyle || document.defaultView.getComputedStyle(element, '') 

という訳で↑これを使えば、クロスブラウザで、しかもワンライナーで getComputedStyle が使える!!テラ便利!!

と、ここで、終わっておけば良かったのですが、、、気になって、、

getComytedStyle について詳しく調べてみた。

getComputedStyle は以下のように ViewCSS というインタフェースに定義されている。

// Introduced in DOM Level 2:
interface ViewCSS : views::AbstractView {
  CSSStyleDeclaration getComputedStyle(in Element elt, 
                                       in DOMString pseudoElt);
};
http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-OverrideAndComputed

そして、 Window Object 草案では Window オブジェクトは ViewCSS を実装しなければならない。

In implementations that support Document Object Model CSS from DOM Level 2 Views [DOM2Views], every Window object MUST also implement the ViewCSS interface.

http://www.w3.org/TR/Window/#window

さらに、 ViewCSS は AbstractView を継承している。

A base interface that all views shall derive from.

http://www.w3.org/TR/DOM-Level-2-Views/views.html#Views-AbstractView

AbstractView はすべての view の基底インタフェースなので、 ViewCSS は view というものということになる。

That is, a view is some alternate representation of, or a presentation of, and associated with, a source document.

http://www.w3.org/TR/DOM-Level-2-Views/views.html

view とは元 document の表現のこと。つまり、 Window Object は document を ViewCSS で表現したものってこと(だと思う)。
document はデフォルトの view を示すために DocumentView というインタフェースを実装してもいいよ。とも書いてある

A Document may implement a DocumentView that has a default view attribute associated with it.

http://www.w3.org/TR/DOM-Level-2-Views/views.html

で、 DocumentView には defaultView というプロパティが定義されている。

It provides an attribute to retrieve the default view of a document.

// Introduced in DOM Level 2:
interface DocumentView {
  readonly attribute AbstractView     defaultView;
};
http://www.w3.org/TR/DOM-Level-2-Views/views.html#Views-DocumentView
つまり

Safaridocument のデフォルトの view (defaultView) は ViewCSS であるが、 window は view ではないというスタンスで実装している。
IE は、 view という概念自体が存在しない。
Firefox, Operadocument のデフォルトの view (defaultView) は ViewCSS であり window である。
ということらしい。実にややこしい

getComputedStyle で取れるオブジェクトは何か

再度ここを見てみると

// Introduced in DOM Level 2:
interface ViewCSS : views::AbstractView {
  CSSStyleDeclaration getComputedStyle(in Element elt, 
                                       in DOMString pseudoElt);
};
http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-OverrideAndComputed

CSSStyleDeclaration インタフェースを実装したオブジェクトということが分かる。
ちなみに、 CSSStyleDeclaratioin は、 element.style とかやって取れるオブジェクトが実装してるインタフェースと同じである。
さらに IE, Opera, Safari, Firefox では、このオブジェクトは CSS2Properties というインタフェースも実装している(はず)。
CSS2Properties のインタフェースは以下のようになっている

// Introduced in DOM Level 2:
interface CSS2Properties {
           attribute DOMString        azimuth;
           attribute DOMString        background;
           attribute DOMString        backgroundAttachment;
:
:
           attribute DOMString        width;
           attribute DOMString        wordSpacing;
           attribute DOMString        zIndex;
};
http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSS2Properties

なるほど、つまり、 element.style とやったときのように簡単に使えるってことですね。

getComputedStyle で取れるオブジェクトはダイナミックか

getComputedStyle で取れるオブジェクトはその時の値を示す静的なハッシュか、それとも元の要素の状態が変わると一緒に変化してくれる動的なオブジェクトなのかが気になった。
いろいろ試してみると元の要素の状態が変わると、一緒に変化してくれることが分かった。

つまり、

<body><p id="target">hoge</p></body>

という html があったとき

var element = document.getElementById('target');
var style = element.currentStyle || document.defaultView.getComputedStyle(element, '');

alert(style.color); // rgb(0, 0, 0)

// ここで <body> の color を変える
document.body.style.color = 'red';

// ちゃんと <p> に継承される
alert(style.color); // rgb(255, 0, 0)

という感じになる。
getComputedStyle で取れるオブジェクトはダイナミックぅ!

まとめ

これであなたも ComputedStyle マスター!