2010-09-02

CSS スタイル定義の優先順位

Blogger のスタイルを変えたい

ここしばらく続けて、CSS のことを調べたり考えたり試したりしているのは、このブログのスタイルを変えたいから。Blogger でこれをやるには、ブログごとに XML で提供されているテンプレートを変更すれば良い。ただ、これが結構面倒なのだ。

なぜ、面倒なのか。まずはテンプレートになっている HTML/XML の構造が複雑なことがある。1 つのテンプレートで表紙から個別ページ、ラベルによる検索結果のページに対応することに加えて、ウェブ上でページ要素(サイドバーなどのコンテンツ)を追加できる等の機能にも対応している。さらに最新版ではテンプレートデザイナーと呼ばれるテンプレートの編集機能にまで対応した作りになっているためだ。

レイアウトを構成する要素のネストは深いく、一番シンプルなテンプレートでさえ、ブログコンテンツの p 要素と body 要素の間に 10 以上の(主に div 要素による)ネストができる。まあ、これは高機能化が複雑さを増すことの良い例ともいえる。

加えて、ユーザが手を出せないスタイルがリンクされることもある。XML のテンプレートを見ているだけではわからないが、実際のブログの HTML ソースを見ると Blogger が提供する CSS ファイルがリンクされていることがわかる。

もちろん、テンプレートにスタイルを記述すれば HTML に直接埋め込まれることになるため、Blogger 提供の外部 CSS の定義を上書きすることは可能だ。実際、これまでそうしてきたし、今回もそのつもりだった。だが、ときどき、この上書きが期待どおりに効果を表さないことがある。これはなぜなのか?

Safari の設定で「メニューバーに"開発"メニューを表示」を有効にしてやると、「Web インスペクタ」が使えるようになる(メニューから「開発」>「Web インスペクタを表示」を選ぶ)。この機能ではページの要素のネストの様子や、各要素に付けられたスタイルの一覧、さらにはスタイルの上書きされている様子も見ることができる。

この機能を使って、期待どおりに効果が表れないスタイルを調べていくうち、ただ単純に後に書かれているから優先になる、というわけではないことがわかってきた。

CSS における優先順位

(「World Wide Web Guide: 段階化の順序」より)
Cascading Style Sheets の Cascade とは順序立てられたリストのスタイルシートという意味から名付けられたもので、スタイルシートが段階的に継承していく働きを表しています。そして、順序立てられたリストの中で記述されている位置やセレクタの違いにより、段階化の順序(スタイル情報が反映される優先順位)は異なってきます。

ブラウザが仕様をどこまで厳密に実装しているかにもよるのだけど、CSS のスタイル定義ではセレクタの書き方によって優先順位が変わる。CSS では基本的に、後の定義が前の定義を上書きする。しかし、優先順位によっては後の定義よりも前のものの方が効果を表すこともある。たとえば、以下の記述の場合、header クラスの div にある h1 に対しては、後ろにある赤色の指定は前の灰色の指定を上書きできない。

(CSS スタイル定義サンプル)
 1: .header h1 { color: gray; }
 2: h1 { color: red }

さて、そのセレクタの記述方法による優先順位だがざっくりまとめるとこんな感じになる。

  • ネスト状況を詳細に記述するほど強い
  • クラス付きより ID 付きが強い
  • ID 付きの数が多いほど強くなる

詳しくは↑で引用したページにある詳細度の定義を見てほしい。その定義にしたがえば厳密に優先順位を判定することができる。

サンプル

以下のような HTML を用意し、リンクした外部 CSS ファイルの記述をあれこれ変えて、実際に 2 つの h1 要素がどんな色で表示されるかを見てみる。基本的には外部 CSS の定義を HTML の head 要素に埋め込まれた定義が上書きをする。外部 CSS 中のセレクタの記述によって、それが変わることを確認できる。

たとえば、こんな CSSの場合、3 行目がネスト状況を一番詳しく記述しているため、(一番前にあるにも関わらず)最優先となり、h1#00ff00 (緑)で表示される。4 行目以降の記述の仕方では 3 行目のスタイルを上書きすることができないことがわかる。また、埋め込みの定義でも上書きできない。

(priority.css)
 1: body { background: white; color: white; }
 2: 
 3: .outer .border .inner h1  { color: #00ff00; }
 4: .outer .inner h1          { color: #0000ff; }
 5: .border .inner h1         { color: #00ffff; }
 6: 
 7: .outer h1                 { color: #008000; }
 8: .border h1                { color: #000080; }
 9: .inner h1                 { color: #008080; }

また、CSS を以下のように変えると、ID 付きでセレクタを書いた定義が優先されることがわかる。

(priority.css)
1: body { background: white; color: white; }
2: 
3: #border1 h1#header1       { color: #008000; }
4: .border h1#header1        { color: #000080; }

Blogger のスタイルを変えるには

現時点では Blogger が提供するテンプレートとスタイルは、iPad や iPhone のようなデバイスに対応していない。iPad や iPhone を特別扱いしたければ、少なくとも CSS によるスタイルの定義をいじらなければならない。そして、そのためにはテンプレートを元に生成される HTML の構造を詳細に知らなければならないのだ。

ネストの深すぎるテンプレートの構造に嫌気がさして、もういっそのことずっとシンプルな構造に変えてやれ、と思ったこともある。テンプレートデザイナーを使うことは、はなからあきらめている。しかし、下手に構造を変えると、ページ要素(ウィジェット)の追加や移動と言った機能も使えなくなってしまう。これは困る。

今の方針は、HTML の構造はなるべくいじらず(背景画像用のレイヤーとか、一部の余分な要素は削る)、セレクタを詳細に記述することですべてのスタイルを再定義する、というものだ。

メディアクエリーによる切り替えだけで済むと思って始めたことだが、なかなか一筋縄では行かない。もうしばらくは、CSS との格闘が続きそうだ。

関連リンク

関連記事

0 件のコメント:

コメントを投稿