JavaScriptでスタイルシートを操作するには?
JavaScriptで既存HTMLページにCSSを追加する必要が出て来たのでちょっと調べた。
基本的に、document.styleSheets
でlink
要素やstyle
要素で読み込まれるスタイルシートが配列風(実際は配列ではない)に参照出来、insertRule
で新規にルールを追加出来るようだ(ただし例によってInternet Explorer以外。IE死ね!)。
const styleSheets = document.styleSheets;
// これで、
// styleSheets[0] = 1つ目のlink或いはstyleで導入されているスタイルシート
// styleSheets[1] = 2つ目のlink或いはstyleで導入されているスタイルシート
// ……といった感じでアクセス出来る。
const styleSheetsNum = styleSheets.length; // スタイルシートの数
styleSheets[0].insertRule( // ルールの追加;一番最初のスタイルシートに……
"a { font-weight: bold; }", // ←のルールを……
0); // 0番目(対象スタイルシート先頭)に挿入。
const ruleNum = styleSheets[0].cssRules.length; // ルールの数
styleSheets[0].insertRule("h1 { color: #000; }", ruleNum); // ←で、スタイルシートの最後にルールを追加出来る。
で、こういった事を解説している、
なんかでは、document.styleSheets
の一番最後にルールを追加するようなコードを載せてる。
でもこれっておかしくない?
スタイルシートのメディアタイプ
link
要素もstyle
要素も、media
という属性を持っている。対象のスタイルシート(link
の場合はスタイルシートに限らないが)を適用する媒体を指定する物だ。例えばmedia="screen"
ならばコンピュータのディスプレイに、media="print"
であれば印刷時に適用される。
さぁ、もしもdocument.styleSheets
の最後のスタイルシートのmedia
が予期しない物だったら?
という訳で、検証用のHTMLを書いてみた。
ソース中にスタイルシートを規定している要素は2つ。どちらもstyle
要素である。1つめのmedia
はscreen
であり、もう片方はprint
である。
<style type="text/css" media="screen">/* <![CDATA[ */
#applies { background-color: #aaaaff; }
/* ]]> */</style>
<style type="text/css" media="print">/* <![CDATA[ */
#applies { border: 1px black solid; }
/* ]]> */</style>
そして、一番最後のスタイルシートにinsertRule
を行うと……
const ssheets = document.styleSheets;
const ssheet = ssheets[ssheets.length - 1];
ssheet.insertRule('#applies { font-weight: bold; }', ssheet.cssRules.length);
JavaScriptで追加したfont-weight
はどうなったか?PCのディスプレイでの表示と、その印刷プレビューのキャプチャを以下に示す。スタイルシート適用先の要素である"APPLIES"と書かれている部分に注目。Firefox 6.0にて確認。
PCディスプレイ側には適用されず、印刷側には適用されている。
これでは、HTML、CSS、JavaScriptを複数人で分業している場合、混乱が生じるのではないか。個人開発でも、上で挙げている解説ページのように関数化して常用していると躓く可能性がある。
既存スタイルシートの操作ではなく、新規にスタイルシートを生成する
ここは『既存のスタイルシートにルールを追加する』のではなく、『ルールを追加する為の新規スタイルシートを追加する』べきだろう。
JavaScript初級者から中級者になろう:五章第三回 CSSの操作のCSSStyleSheetの追加と削除
を参照すると、style
要素を生成し、そのsheet
プロパティにアクセスすれば良いようだ。
var style = document.getElementsByTagName('head')[0].appendChild(document.createElement('style'));
style.type = 'text/css';
style.sheet.insertRule(追加するルール, style.sheet.cssRules.length);
では、例えばそのページのメンテナンスをするのが自分自身であり、media
に関する問題を起こさないと言える時には『最後のスタイルシートにルールを追加』しても良いのだろうか?そうは思えない。
昨今のwebブラウザはアドオンをサポートしている物が多い。それらは勿論の事、Greasemonkeyのように、ページに対し閲覧者が任意のスクリプトを実行する場合さえある。それら(或いは彼ら)が、ページ中にスタイルシートを追加しないとどうして言い切れるだろうか。
Skype Extension for Firefox と Security error" code: "1000 - てっく煮ブログではSkype Extension for Firefox はお行儀が悪い
と言っているが、少なくともスタイルシートに関しては、その意見に同意出来ない。幾つもの要素をページ中に挿入するアドオンの場合、生成した全ての要素のstyle
プロパティを同一の内容にするよりも、1つのスタイルシートを生成した方がより利口だろう。nitoyon氏の書いたJavaScriptの方が"お行儀が悪い"のではないだろか。
I have Twitter account, but I stopped what use it.
Alternatively, I'm using Google+ ( https://plus.google.com/110360324196605830601 ).