スタイルシートをまとめて動的に設定する

JavascriptCSSを動的に設定するとき、普通は次のようにしますね。

document.getElementById("hoge").style.display = "none";


IDでelementを取得し、そのstyleのdisplayにnoneを設定・・・って正直面倒っちいです。
いっぱい設定しようと思ったら、一行一行書かないといけないし、
classに同じスタイルを設定しようと思ったら、ノードをfor文で回してclassを見て・・・気が遠くなります。


そんなときはelementにスタイルを設定するのではなく、動的にスタイルシートを追加しましょう。

var css = (function() {
    var s = document.createElement('style');
    s.setAttribute("type", "text/css");
    document.getElementsByTagName('head').item(0).appendChild(s);
    var ss = s.sheet;
		
    return function(sel, sty) {
        ss.insertRule(sel + "{" + sty + "}", 0);
    };
})();


使い方も簡単、第一引数にセレクタ、第二引数にスタイルを入れます。
普通のスタイルシートと基本的にはおんなじ書き方で使えます。

css("#hoge", "display: none;");
css(".piyo", "background: gray; width: 50%;");

何となく解説

基本的には無名関数とクロージャです。
いいですね、クロージャ
Javascriptのトリッキーさの先駆けみたいな感じがして好きです。


しかしクロージャについて説明するのとってもモニョモニョするので、ぜひ自分で調べてください。
僕はこちらを見て何となく理解しました。
[JavaScript] 猿でもわかるクロージャ超入門 1 問題 · DQNEO起業日記
JAVAでいうとPrivateなメンバやメソッドを操作できる、staticなメソッドを公開できるようなものかなーと。
多分違うけど。
どっちにしろこれJava知らない人には全然伝わんないと思います。
まあその程度の理解なので、間違っていたら指摘してください。
あ、そんな私の仕事の種であるJavaにはクロージャはありません。
Java7で採用されると思ったけど、そんなことは無かったぜ!


さて、まずはcreateElementで<style>要素を作ります。
それにtype属性をつけて<style type="text/css">を作ります。

var s = document.createElement('style');
s.setAttribute("type", "text/css");

それを<head>の子要素として追加します。
getElementsByTagNameの戻り値は配列(2012/5/3追記:これは配列ではなくNodeListオブジェクトですね。コメントにて指摘頂きました。ありがとうございます)ですが、<head>は必ず一つだけなのでitem(0)とします。
<style>のsheetを変数ssに入れます。
これがスタイルシートオブジェクトです。

document.getElementsByTagName('head').item(0).appendChild(s);
var ss = s.sheet;

css("", "")で実行されるのが次のクロージャ部分です。
外側からはこの内部しか見えませんが、クロージャの中からは一つ外側のssオブジェクトが見えるわけです。
これをレキシカルスコープといいます。

return function(sel, sty) {
    ss.insertRule(sel + "{" + sty + "}", 0);
};


あとは最後にfunctionの無名関数を()();で囲んで即実体化してます。
CSSインスタンスは複数はいりませんから、これでオブジェクトの実体を一つだけに制限します。
JavaでいうSingletonに近いのかな。