JavaScriptでCSSStyleSheetオブジェクトを生成するには

使うので調べてみたことを書いてみる。Mozilla Firefox 1.5とか限定…というより、ほかのブラウザでは確かめてない。
(X)HTMLstyle要素に書くCSS全体は、JavaScript(というよりDOM Level 2 Style)ではCSSStyleSheetオブジェクトで表される。

<html>
  <head>
    <title>みだし</title>

    <style type="text/css">
      /* ここに書くCSS全体はCSSStyleSheetオブジェクトで表される */
    </style>
  </head>
  <body>
    <p id="target">ほんぶん</p>
  </body>
</html>

documentオブジェクトにはstyleSheetsプロパティがあって、こいつでCSSStyleSheetオブジェクトにアクセスできる。DOM Inspectorふうに書くとこうなる。

プロパティ      値
------------------------------------------------
document        [object HTMLDocument]
└styleSheets   [object StyleSheetList]
 ├0           [object CSSStyleSheet]
 ├1           [object CSSStyleSheet]
 ├2           [object CSSStyleSheet]
 :
 ├length      (長さ)
 └item        function item() { ... }

例えば、style要素の内容を表示するにはこうする:

for(var i = 0; i < document.styleSheets.length; i++) {
  alert(document.styleSheets[i].ownerNode.innerHTML);
}

さて、CSSStyleSheetオブジェクトを生成するにはどうすればよいかというと、style要素を挿入するだけでよい。

// 名前空間とかはとりあえず気にしないことにする。
var head     = document.getElementsByTagName('head')[0];
var styles   = head.getElementsByTagName('style')[0];
var newStyle = document.createElement('style');

newStyle.type = 'text/css';

// 先頭に挿入してみる
// (生成したCSSStyleSheetオブジェクトはdocument.styleSheets[0]になる)
head.insertBefore(newStyle, styles[0]);

CSSStyleSheetオブジェクトはstyle要素に書くCSS全体を表すので、@mediaとか:hoverみたいのも書ける。

newStyle.innerHTML = '#target:hover { background: gray; }';

CSS全体ではなく)各ルールにアクセスするには、cssRulesプロパティを使う。

プロパティ      値
------------------------------------------------
document        [object HTMLDocument]
└styleSheets   [object StyleSheetList]
 ├0           [object CSSStyleSheet]
 │├cssRules  [object CSSRuleList]
 │├0         [object CSSRule] (具体的に何になるかはstyle要素の内容による)
 │├1         [object CSSRule]
 │├2         [object CSSRule]
 │:
 │├length    (長さ)
 │└item      function item() { ... }
 ├1           [object CSSStyleSheet]
 ├2           [object CSSStyleSheet]
 :
 ├length      (長さ)
 └item        function item() { ... }


…何のためにこんなのを調べたのかというと、Greasemonkeyユーザスクリプトで「印刷されないメッセージ」とか「マウスカーソルをホバーすると現れる、じゃまにならないメニュー」みたいのを作りたかったからだ。