Mozilla Bugzilla 564667 comment#37 を見てようやく stylesheet (CSSの反映) の動的追加削除の方法を知った。 (下記引用、体裁は修正している)

I also filed bug 675387 for overlay directives, but there's no capability to unload them at this time so that one will probably have to wait a while.

Do we care about supporting style overlay directives here, and if so is the capability also missing along the lines of XUL overlays?

I don't think there is an API to do it right now, but I think it'd be simpler to add one than for overlays for example. I believe style lines just wind up as xml-stylesheet lines in the DOM.

要するに、<?xml-stylesheet ...>を動的に追加削除すればよいという。

stylesheet の動的追加

例えば、ブラウザウィンドウを開いた時などで、restartless (bootstrap) 拡張は DOM で XUL 要素を追加するが、これと同じタイミングで stylesheet を動的追加する。 stylesheet の動的追加の方法を以下に示す。

この<?xml-stylesheet ...> -- XML の規格にそうと processing instruction という -- は下記のようにして動的に追加できる。

var pi = document.createProcessingInstruction('xml-stylesheet',
          'href="chrome://foobar/skin/foobar.css" type="text/css"');
document.insertBefore(pi, document.documentElement);

一般に processing instruction は任意の場所に挿入できるのだが、 xml-stylesheet の場合はルート要素(ドキュメント要素)の前に入れないといけない。 そのため、上の例ではルート要素の直前に挿入するコードとなっている。

stylesheet の動的削除

例えば、ブラウザウィンドウを閉じた時などで、restartless (bootstrap) 拡張は DOM で XUL 要素を削除するが、これと同じタイミングで stylesheet を動的削除する。

<?xml-stylesheet ...> を削除すれば元通りに戻せるが、 この処理は、 普通に要素を探して removeChild() すればよい。

for (var i = 0; i < document.childNodes.length; i++) {
  var child = document.childNodes[i];
  if (child.nodeType == Element.PROCESSING_INSTRUCTION_NODE) {
    if ((child.nodeName == 'xml-stylesheet') &&
      (child.nodeValue.indexOf('href="chrome://foobar/skin/foobar.css"') >= 0)) {
      document.removeChild(child);
      break;
    }
  } else if (child == document.documentElement) {
    break;
  }
}

余計な補足(念の為)

  • Restartless (bootstrap) では ない 従来型拡張 (traditional extension) については、 普通に overlay の XUL ファイルに <?xml-stylesheet ...> を書いておくか、 または chrome.manifest で style overlayを利用する。
  • 今回の目的とは若干異なるが、XUL といった XML ではなく、HTML についてはこのようなことをする場合は、同様に <link rel="stylesheet" ... /> の動的追加削除をすればよい。

実は nsIStyleSheetService インタフェースがあった。

と張り切って書いたものの、XUL アプリ的には nsIStyleSheetService を使えということらしい。 なお、非XULならば、ここで述べた方法をとる必要がある。 (2014-03-15追記。)

Reference