Web標準普及プロジェクト

:hover疑似クラスは宣言順序に注意が必要です

ユーザの操作によって動的に状態が変わり、その状態を指し示すのがCSSの動的疑似クラスです。 この動的疑似クラスを用いるとJavascript等を用いなくても見た目に動的っぽいページを作ることができるので、 近年多くの人が採用しているように思えます。 しかし、この動的疑似クラスは宣言の順序に注意が必要です

実際に発見された間違い

以下のように宣言したとしましょう。 おそらくこのシートを記述した人はアンカーの上にマウスカーソルがある場合は赤、未訪問なら黒、訪問済なら緑のテキストで表示されることを期待したと思います。

a:hover{
	color:red;
}
a:link{
	color:black;
}
a:visited{
	color:green;
}

未訪問
訪問済

さて、どのように動作したでしょうか?IE6、Mozilla、Operaとそれぞれ全く異なる動作なのですが、 正解はMozillaの動作です。Mozillaではマウスカーソルがアンカーテキストの上に乗っても色は赤くなりません。

後から設定した値が優先されるCSS

CSSには段階化規則というものがあり、ある条件に対して値を複数回指定すると、最後に指定されたものが有効になります。 今回の例では一見期待通りに設定されそうですが実際はそうではありません。 では、その設定のプロセスを見てみましょう。

:link :visited :link:hover :visited:hover
a:hover{color:red;}を適用 初期値 初期値 red red
a:link{color:yellow;}を適用 black 初期値 black red
a:visited{color:green;}を適用 black green black green

と、なるわけです。:link,:visitedのような疑似クラスは動的疑似クラスにも設定値の影響が出るのです。 つまり、次のように書くのが正解です。

a:link{
	color:black;
}
a:visited{
	color:green;
}
a:hover{
	color:red;
}

未訪問
訪問済

この時ブラウザ内部では次のように値が設定されていくわけです。

:link :visited :link:hover :visited:hover
a:link{color:yellow;}を適用 black 初期値 black 初期値
a:visited{color:green;}を適用 black green black green
a:hover{color:red;}を適用 black green red red

同様に、疑似クラスを付加しないa要素への値設定等は疑似クラス、動的疑似クラスと双方との値の衝突を意識しなくてはいけません。 詳しくは次の表を見てください。

:link
:link:hover :link:active :link:focus
:link:hover:active :link:hover:focus :link:hover:active:focus :link:hover:active :link:active:focus :link:hover:active:focus :link:hover:focus :link:active:focus :link:hover:active:focus

この表は各クラスにの与える影響範囲を表したものです。 いずれかに対して指定を行うと、そのセルより下側に来る全てのセルに対して影響が出る、と見てください(:link疑似クラス指定の影響範囲の大きさがわかるでしょう)。 実際にソースを記述する際にはこの表の上にあるものから、下にあるものへと宣言してやることで、Mozillaのように正しい解釈のできるブラウザでは細かい表示制御が可能になります。