:active
疑似クラスは親要素に伝搬しないものすごく久しぶりに Blog 書いてるなぁ……。書こうと思えば書けたのだが。さて、ここから本題。「IE8 & Opera 9.5 以降」と「Firefox & Safari & Google Chrome & Opera 9.2x」を比較すると、:active
疑似クラスが親要素にも伝搬するか否かがそれぞれ異なっている。
結論からいえば、次の状況になっている。
UA | :hover |
:active |
---|---|---|
Firefox 3.0.8 | ○ | ○ |
Firefox 3.5 Beta 4 | ○ | ○ |
Safari 3.2.3 | ○ | ○ |
Safari 4 Beta (AppleWebKit/528.18) |
○ | ○ |
Opera 9.27 | ○ | ○ |
IE8 | ○ | × |
Opera 9.52 | ○ | × |
Opera 9.64 | ○ | × |
Opera 10.00 (Build 1497) |
○ | × |
:active
疑似クラスは UA によって挙動が異なっているのがわかる。
対照的に、:hover
疑似クラスはどの UA でも常に親要素へ伝搬している。
この現象は、UA によって :active
と :hover
の伝搬に差異があるという問題につながっている。
次の div
要素には、各々に :hover
疑似クラスと :active
疑似クラスが定義されている。各要素は「疑似クラスが割り当てられた」ことを認識すると :before
疑似要素にてその旨を表示するようになっている。
この問題はかなり根が深いようで、CSS 2 ではそもそも挙動自体が言及されていなかったようだ。
CSS 2 では次のように記述されている。
CSS doesn't define which elements may be in the above states, or how the states are entered and left. Scripting may change whether elements react to user events or not, and different devices and UAs may have different ways of pointing to, or activating elements.
5.11.3 The dynamic pseudo-classes: :hover, :active, and :focus
CSS 2.1 では強調部分が追記されている。
CSS doesn't define which elements may be in the above states, or how the states are entered and left. Scripting may change whether elements react to user events or not, and different devices and UAs may have different ways of pointing to, or activating elements.
CSS 2.1 doesn't define if the parent of an element that is ':active' or ':hover' is also in that state.
5.11.3 The dynamic pseudo-classes: :hover, :active, and :focus
Selectors Level 3(CSS 3 のセレクタ仕様)にも強調部分のように、CSS 2.1 と同様の表現が存在している。
There may be document language or implementation specific limits on which elements can become :active or acquire :focus.
These pseudo-classes are not mutually exclusive. An element may match several pseudo-classes at the same time.
Selectors doesn't define if the parent of an element that is ':active' or ':hover' is also in that state.
つまるところ、CSS 2、CSS 2.1、CSS 3 のどれにも :active
及び :hover
疑似要素の挙動が明示されていない。この現状が、各 UA 間で挙動が異なってしまっている原因のひとつだと考えられる。
本サイトのメインナビゲーション(現時点では右上)は、:active
疑似クラスを多用している。つまり、前述してきた UA 間で起こる挙動の差異に巻き込まれてしまう。現に、IE8 & Opera 9.5 以降では意図した通りの挙動を起こさない。該当 UA でメニューボタンを押下してみてほしい。ボタンの一部しか押下の挙動を示さず、レイアウトが崩れてしまっているはずだ。これは a
要素で発生した :active
疑似クラスが、親要素である li
要素に伝搬していないために、li:active
が解釈されないために起きている。
Opera 9.5 時代からこの問題は把握していたが、原因の特定までは行っていなかった。ところが IE8 でも同様の挙動をとることが判明し、慌てて調査してみたというわけである。何とも情けない話であるが、有益な情報を得ることができたと思う。
DOM 2 Events の概念に照らしていえば、:active
疑似クラスの挙動は次のようにまとめることもできる。
active
イベントが bubbing しない。
active
イベントが bubbing する。
IE8 & Opera 9.5 以降の bubbling しない 挙動は、ある意味で非常に直感的でないともいえる。CSS と DOM の仕様は別々に策定されているため、こういった差異が生じるのはわからなくもないが、せめて仕様書には正となる挙動を明示して欲しかった。
こういった「非明示による差異」問題は、他にも細かいところでありそうだ。ただ、細部を意図的に明示しないのは W3C の意図という話をどこかで聞いたことがある。HTML/XHTML も例外ではない。その反動が WHATWG による HTML 5 の細かさに繋がっていたりするらしい、という話もどこかで聞いた。
しかし、この :active
の問題は、どうみても不利益しか生まないような気がする。どうして不明瞭な文面にしたのだろう。意図が知りたいなぁ……。