body の overflow: hidden が変
以下のようなコードがあって
... <html> ... <body> <div></div> </body> </html>
body が overflow hidden で幅固定で div が横に伸びていったら div は body を「はみ出ない」と思うんだ。
でも、ブラウザによってははみ出てしまう。
この変は見てみたけど
http://www.w3.org/TR/CSS21/visufx.html#overflow
「はみ出ない」のが正しい気がする。
style.cssText の使い処に関する考察
cssText って知ってますか?
cssText っていいうのは CSSRule オブジェクトとか CSSStyleDeclaration が持っている情報を css ファイルに書く形式の文字列にしてくれる機能です。
乱暴に言ってしまえば、 css 系のオブジェクトが持っている innerHTML みたいなものです。
具体例を見てみましょう。
こんな感じの body があるときに
<body style="margin: 1em; padding: 1em; border: 1em">....</body>
こんな感じで使えます。
alert(document.body.style.cssText); // 'margin: 1em; padding: 1em; border: 1em'
簡単でしょう?(ボブ略
設定も出来ますよ
こんな感じ
// さっきの続き document.body.style.cssText = 'width: 100px'; alert(document.body.style.margin); // '' alert(document.body.style.padding); // '' alert(document.body.style.border); // '' alert(document.body.style.width); // '100px'
簡単でしょう?
で、
あんまり使う必要なくね?
うんうん。そう思う
でも
さっき便利な使い方を 3 つ思いついたので紹介します。
デバッグ時に値を見るとき
これは普通に便利。
いちち style.xxxx を書くのがめんどくさいとき
うん。あるある。
スタイルをキャッシュしておいて戻したりしたいとき(本題)
たとえば、キャッシュしておいて
var style = element.style; var cache = style.cssText;
いろいろいじっても、元に戻せる機能を付けたいとか。
style.cssText = cache; // これだけで元の style に戻せる。
便利!
ちなみに
実はこれよりもっと効率的な方法があるのですが、その方法は IE では動きませんでした。その方法は以下。
// キャッシュするとき var style = element.style; var cache = {}; for (var i = 0, l = style.length/*←IEではこれがない*/; i < l; i ++) { var n = style[i]; // ←IEではこれもない cache[n] = style[n]; } // 戻すとき for (var i = 0, l = style.length; i < l; i ++) { var n = style[i]; if (!(n in cache)) { // キャッシュにないプロパティは削除 style[n] = ''; } } for (var n in cache) style[n] = cache[n]; // キャッシュされてるものを戻す
長ったらしいけど、これが一番効率的だと思います。
もちろん、全プロパティを走査すれば簡単にキャッシュできるのですが、それだと激重です。
Opera の CSSStyleSheet.insertRule はちょっとバグってる
以下のコード
var element = document.createElement('style'); element.appendChild(document.createTextNode('')); document.getElementsByTagName('head')[0].appendChild(element); var sheet = element.sheet; // 以下のように CSSStyleSheet の先頭に二つのルールを挿入していく sheet.insertRule('html body { background: gray }', 0); // 0 番目にこのルールを挿入 sheet.insertRule('html body { background: red }', 0); // 0 番目にこのルールを挿入
このようにするとルールの順番は html body { background: gray } のほうが下にくるので、
カスケーディング順位(CSS のルールの優先順位)は html body{ background: red } より html body{ background: gray } のほうが上位になるはずである。
ということはこれを実行すると、body 要素の背景は gray になるはずである。
しかし Opera では
背景は red になってしまう。
これは、 Opera が insertRule の第二引数に関わらず、ルールをルールリストの最後に挿入してしまうためである。
ブックマークレット化したので、実際にやってみてください。(IE は全くの独自仕様なのでこのブックマークレットはうごきません。あしからず)
javascript:var element=document.createElement('style');element.appendChild(document.createTextNode(''));document.getElementsByTagName('head')[0].appendChild(element);var sheet = element.sheet;sheet.insertRule('html body { background: gray }', 0);sheet.insertRule('html body { background: red }', 0);void(0);
まとめ
現状 insertRule を使う場合は、以下のようにルールをルールリストの最後に追加しなければブラウザ間の整合性が保てなくなってしまう。
sheet.insertRule('html body { background: black }', sheet.cssRules.length);
まあ、 IE 独自の addRule も最後にしか挿入できないし、どっちにしろそうなんだけどね(ぇ
Safari で CSSStyleSheet オブジェクトを生成する方法
今まで Safari では出来ないと思っていました
var element = document.createElement('style'); document.getElementsByTagName('head')[0].appendChild(element); var sheet = element.sheet; alert(sheet); // null
こんな感じで null になってしまうのです。。。
しかし!
さっき出来る方法が分かりました!
var element = document.createElement('style'); element.appendChild(document.createTextNode('')); // この行を追加 document.getElementsByTagName('head')[0].appendChild(element); var sheet = element.sheet; alert(sheet); // [object CSSStyleSheet]
このように TextNode を追加することで sheet オブジェクトが取得できるようになりました。
あー。どうして今まで試さなかったんだろう!
でも、分かってスッキリ!
document.createStyleSheet で動的に CSS を生成
今まで
var element = document.createElement('style'); document.getElementsByTagName('head')[0].appendChild(element); if (ie) { var sheet = element.styleSheet; } else { var sheet = element.sheet; }
みたいにやっていた。
ところが
createStyleSheet を使うとこうなる。
if (ie) { var sheet = document.createStyleSheet(); } else { var element = document.createElement('style'); document.getElementsByTagName('head')[0].appendChild(element); var sheet = element.sheet; }
あまり代わり映えはしないけど。無駄な要素を挿入しなくてもいいので、こっちのほうが軽いかな。
IE は多数派なので、直しておこうっと。
Safari3 では :checked :disabled :enabled が使えるっぽい
でも
<label> を横に並べて、 :checked + label とかやっても label は変わらなかった。まだバグがあるようだ。
:lang(en) とかも
使えるみたいだけどバグだらけで使いものになりませんでした。バージョンアップに期待。
getComputedStyle について調べてたら深みにハマったのでメモ
getComputedStyle とは!?
ある要素にどんなスタイルが当たっているかを計算してくれる。便利な関数。
使いかたはめっちゃ簡単!
var style = getComputedStyle(element, ''); alert(style.fontSize); // 14px alert(style.color); // rgb(0, 0, 0)
ちなみに第二引数は疑似要素の style を取りたい場合に使います。通常は空文字列でいい。
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
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 マスター!