警告: この記事の内容は古くなっている可能性があります。 MDNへの記事の移行が 2007 年、
記事自体の最終更新は
2000 年です。
以下の文書では Mozilla の UI で使用する CSS ファイルの最適化についての規則を概説します。最初の節では Mozilla のスタイルシステムにおけるルール分類の要について書きます。このシステムについて理解してもらった上で、続く節では Mozilla のスタイルシステムの力を最大限に発揮するルールの書き方を説明します。
【訳注: CSS スタイルのマッチング処理に於いては、ルール集合のうち各要素に対してマッチするものがないか順に全て調べていく必要があり、単純計算では (要素数)×(ルール数) 回のマッチング処理が必要になってしまいます。如何にしてこれを効率化するのか、それがこの文書の主題です。】
なおこの文書は Mozilla の UI で使用する CSS についての規則として書かれていますが、一般のWebPageにおいても Mozilla での描画速度を向上させるために有効です。後方互換性や文書構造を考えると一般のWebPageでは予備知識として知っておく程度でも十分ですが、CSSを多用しており複雑で読み込み時間の長いページがあれば、CSSルール記述を変えてみるのも良いかも知れません。
スタイルシステムによるルール分類
スタイルシステムは CSS ルールを大きく 4つの区分に分けて扱います。ルールマッチングに於いてはこの振り分けが速度低下からブラウザを守る第一防衛線であり、この区分の理解が必須となります。以下の段落では キーセレクタ という用語を使用します。 IDセレクタ、クラスセレクタ、タグセレクタのうち最も右に現れるセレクタをキーセレクタと定義します。
ID ルール
最初の区分はキーセレクタで ID を指定しているルールです。
例
button#backButton { } /* これは ID 指定されたルール */ #urlBar[type="autocomplete"] { } /* これは ID 指定されたルール */ treeitem > treerow > treecell#myCell :active { } /* これは ID 指定されたルール */
クラスルール
キーセレクタでクラスを指定しているルールはこの区分とします。
例
button.toolbarButton { } /* クラス指定されたルール */ .fancyText { } /* クラス指定されたルール */ menuitem > .menu-left[checked="true"] { } /* クラス指定されたルール */
タグルール
キーセレクタでクラスや ID が指定されていなければ、次に考えられるルール区分はタグ区分です。キーセレクタでタグが指定されているルールがこの区分に分類されます。
例
td { } /* タグに拠るルール */ treeitem > treerow { } /* タグに拠るルール */ input[type="checkbox"] { } /* タグに拠るルール */
一般ルール
その他のルールは全てこの区分のものとします。
例
:table { } /* 一般ルール */ [hidden="true"] { } /* 一般ルール */ * { } /* 一般ルール */ tree > [collapsed="true"] { } /* 一般ルール */
スタイルシステムによるルールマッチング
スタイルシステムは個々のルールについて、対象要素にマッチするかどうかルール中のセレクタを一番右に書かれたセレクタから順々に確認していきます。【訳注: (スタイルルールセレクタの)】ツリーが【訳注: (対象要素のコンテクストに)】適合し続けている限り、スタイルシステムはルールがマッチするかミスマッチで終了するかするまで【訳注: (ルールツリー中のセレクタを)】順に確認し続けます。ここでの第一防衛戦が、キーセレクタ種別によるルールフィルタリングです。この分類の目的はマッチ確認で時間を無駄にしないよう、ルールをふるいにかけることです。これがパフォーマンスを劇的に向上させる鍵なのです。与えられた要素に対して確認しなければならないルールが少ないほど、スタイル決定は速くなります。例を挙げると、対象要素が ID を持っている場合 ID ルールの中でその要素の ID にマッチする ID ルールだけが確認されます。クラスルールは対象要素に指定されたクラスに対応するルールだけが確認されます。タグルールについても、対象要素にマッチするものだけが確認されます。一般ルールはすべての要素に対して確認されてしまいます。
効率的 CSS を書く為の指針
一般ルールを使用しないこと!
ルールが一般区分になってしまわないようにすること!
ID 区分のルールにタグ名やクラスを指定しないこと!
ID は一意なものでありそれだけで対象要素を特定できるので、スタイルルールがキーセレクタとして IDセレクタを持つのであれば余計なタグ名まで追加しないこと。処理を遅くするだけで何の意味もありません。
- ダメ -
button#backButton { }
- ダメ -
.menu-left#newMenuIcon { }
- 良し -
#backButton { }
- 良し -
#newMenuIcon { }
クラス区分のルールにタグ名を指定しないこと!
上記のルールと同様に、クラスは全て固有なものにすることが出来ます。タグ名を含めたクラス名を使用するようにしてください。
- ダメ -
treecell.indented { }
- 良し -
.treecell-indented { }
ルールを出来る限り細分化された区分に入れるようにすること!
システムを遅くする最も大きな原因を 1つ挙げるとすれば、タグ区分に多くのルールがあり過ぎるということです。要素にクラスを追加することでこれらのルールをクラス区分のものとすることができ、各タグに対して多くのルールを確認して時間を浪費せずに済みます。
- ダメ -
treeitem[mailfolder="true"] > treerow > treecell { }
- 良し -
.treecell-mailfolder { }
子孫セレクタの使用を避けること!
子孫セレクタは CSS の中で最も贅沢なセレクタです。特に子孫セレクタを使用しているルールが タグ区分や一般区分であれば恐ろしく高くつきます。大抵は実際に必要とされているのは子セレクタです。スキンのモジュールオーナによる明示的な許可がない限り UI で使用する CSS では子孫セレクタの使用が禁止されています。
- ダメ -
treehead treerow treecell { }
- マシだが、まだダメ (次を参照) -
treehead > treerow > treecell { }
タグ区分のルールは決して子セレクタを含まないように!
タグ区分のルールで子セレクタを使用するのは避けてください。当該要素の出現毎のマッチ時間を(特にそのルールが頻繁にマッチする場合には)劇的に短くすることが出来ます。
- ダメ -
treehead > treerow > treecell { }
- 完璧 -
.treecell-header { }
全ての子セレクタ使用を疑え!
子セレクタの使用には注意してください。使用を避けて済ませる方法が見つかれば、そうして下さい。特に、RDF ツリーとメニューで子セレクタがこのように使われてしまうことが多くあります。
- ダメ -
treeitem[IsImapServer="true"] > treerow > .tree-folderpane-icon { }
RDF による属性はテンプレートに写す事が出来るということに注意を! それを活かして、属性に応じて変化させたい XUL 子要素に RDF のプロパティを写すようにしてください。
- 良し -
.tree-folderpane-icon[IsImapServer="true"] { }
継承に任せなさい!
どのプロパティが継承されるかを学び、継承されるようにしてください! XUL ウィジェットは親タグに list-style-image (単なる一例) や font ルールを指定することで無名コンテントにも継承されるように構成されています。無名コンテントに直接作用するルールを書いて時間を浪費する必要はありません。
- ダメ -
#bookmarkMenuItem > .menu-left { list-style-image: url(blah); }
- 良し -
#bookmarkMenuItem { list-style-image: url(blah); }
本来このルールは最も限定的な区分である ID 区分となるべきものなのに、(list-style-image が継承されることを知らずに) 無名コンテントのスタイルを指定しようとすると、上の例のようにクラス区分のルールになってしまうのです。
無名コンテントはすべて同じクラスであることに注意してください! 上のダメな例を使用してしまうと、全てのメニューアイコンについてそれがブックマークメニューアイテムの中にあるかどうか調べることになります。これはぞっとするほど高くつきます(メニューの数は多いですから)。このルールがマッチ確認されるべきなのはブックマークのメニューに対してだけです。
-moz-image-region を使いなさい!
画像をばらばらのファイルに配置するよりも、まとめて一つの画像にして -moz-image-region
によって表示する画像を選択するようにした方がパフォーマンスはかなり向上します。
原文情報
- 著者: David Hyatt
- 最終更新日: 2000 年 4 月 21 日