:hoverしている要素の直前の要素の指定をCSS4の!符号で妄想した

※これは「そうなったらいいなあ、こういうふうにできたら僕は都合がいいなぁ」という妄想であり、CSS の仕様を解説する記事ではありません

CodePen にあったStairway Navというサンプルが Flash ぽくて格好よいのだけど、:hover してる前の要素の取得に JavaScript を使っているのを見て、これが CSS だけでできたらいいのにと思った。2012/8/23 時点の Selector Level 4 の Working Draftでももちろんそんな都合のいいセレクタは存在していない。あったらいいのに。

ということで妄想してみた。やるとしたらE! > Fで「F を直接の子要素にもつ E 要素」をスタイリング対象にできるという「!」マークを使う。

<ul>
  <li>たまご</li>
  <li>ごはん</li>
  <li>しょうゆ</li>
  <li>かつおぶし</li>
  <li>食べたい気持ち</li>
</ul>

このような HTML があったとして、

li! + li:hover{...}

このように書けば、「li:hover を隣接要素に持つ li」という解釈になり、見た目として:hover している li の直前の li をスタイリング対象にすることができるのではないだろうか。さらに、:hover の2つ前の li を対象にしたい時はこんな具合か。

li! + li + li:hover{...}

:hover した li 以前の全ての li を対象にしたい場合はこうか。

li! ~ li:hover{...}

実現できたら素晴らしいが、それにしても li 要素に!マークは視認性が悪すぎる!

......妄想は以上です。

ところでこの!マークはなんて呼べばいいのだろう。冒頭リンクの Working Draftだと「Determining the Subject of a Selector」として解説されている。Subject は英文法 SVO の S だから、「セレクターの主部の決定」と訳せる。そうなると「主部決定符号」とか? なんだかしっくりこない。プロパティを適応する対象を決定するのだから「対象符号」と呼ぶのはどうだろうか。うん、それがいいと思う。

対象符号は 2011 年の Working Draftでは「$」マークで要素の前に設定されていたけど、「!」に変わり付加位置も要素の後ろに変わった。そのおかげでこんな ISSU があがっている。

Should the exclamation mark be prepended or appended to the subject? Or both? Or prepend two, to avoid the "! = not" issue?

抄訳: !マークは対象要素の前と後ろ、どっちにつける? 前と後ろの両方に付ける? もしくは、"◯◯ でない" という意味にならないように要素の前に2つ付ける?

要素を!で挟む形になるのも気持ち悪いし、!を2個つけるのも気持ち悪い。

 $E > F {...} /* Old Draft */
 !E > F {...} /* looks like "!=not" */
!E! > F {...} /* OMG */
!!E > F {...} /* is mean not not-E? */
 E! > F {...} /* Working Draft in 2013-5-2 */

「!=not」はプログラムやる人にはお馴染みのやつで、そう言われればたしかに違和感ある。ちなみに E:not という擬似クラスセレクタはすでにある。

最初の「$」でいいじゃんと思っていたけど、Sass との衝突を避けるため別の記号にしたんだっけか。主要な記号はそういったプリプロセッサで使われているから上手いの考えるのが難しそう。かと言って!important みたいなのは止めて欲しい。:parentなんていう書き方を妄想してる人もいた(2010/10/21)。:parent では隣接セレクタには対応できない。倣うなら:siblingだろうか。つらそう。

最終的に「Determining the Subject of a Selector」はどんな仕様になるんだろう。早く使いたい。

2013/5/2 に Selectors Level 4 の Working Draft が更新されているが、Determining the Subject of a Selector については変更はないようだ。