CSSを追加する関数
の39番目とGM_addStyleの実装と最適化 - 0xFFについて。
まず、style要素を使う方法。
function addStyle(css) { var style = document.getElementsByTagName('style').item(0); if (!style) { style = document.createElement('style'); style.type = 'text/css'; (document.getElementsByTagName('head').item(0) || document.documentElement).appendChild(style); } style.appendChild(document.createTextNode(css + '\n')); }
元からあるstyle要素を利用する方法。コメント欄参照。うまくいく。これはうまくいかない。HTMLのページだと、style要素の中身が当然、createCommentで生成したCommentノードを追加しても無視される。<!-- body { color: blue; } -->
のようにコメントで括られた物になっている事があって、(style.firstChild instanceof Comment
ではない)ので、普通にtextNodeを追加すると、<!-- body { color: blue; } --> body { background-color: red; }
のようになって正しく解釈されない。
そして、createTextNodeだと元からあるCSSが再パーズされるんじゃないかと思ってこの方法は使ってない。
次に、link要素を作る方法。
function addStyle(css) { var stylesheet, link; if (!addStyle.__link) { stylesheet = document.createElement('link'); stylesheet.rel = 'stylesheet'; stylesheet.type = 'text/css'; addStyle.__link = stylesheet; } link = addStyle.__link.cloneNode(true); link.href = 'data:text/css,' + encodeURI(css); (document.getElementsByTagName('head').item(0) || document.documentElement).appendChild(link); }
や、closureを使って
var addStyle = function () { var stylesheet = null; return function (css) { var link; if (!link) { stylesheet = document.createElement('link'); stylesheet.rel = 'stylesheet'; stylesheet.type = 'text/css'; } link = stylesheet.cloneNode(true); link.href = 'data:text/css,' + encodeURI(css); (document.getElementsByTagName('head').item(0) || document.documentElement).appendChild(link); } }();
とする方法。この方法は、関数を呼ぶ度にlink要素が毎回作られる。deadspaceで使っている物と似ているが、btoaを使っていないので、a:visited::before { content: "既読"; }
のような日本語が入っているCSSでもエラーにならない。dataスキームにしたいだけならbase64を使う必要はない。
他にはdocument.createCDATASectionを使ったりdocument.styleSheets.item(0).insertRuleなどが考えられるが、前者はHTMLでは使えないしXMLの場合でもCSSに]]>という文字が入れられない。後者は複数のスタイルを同時に追加できないので要件を満たしていない。
結論は、link要素を追加するのがいいと思う。