@ushironoko
このエントリでは div[role="presentation"]:first-of-type というセレクタを使用しているが、これはぱっと見て危うい
display:noneするかわりにハイライトするスタイルをつけてみる
すると、目的以外のところにも誤ってマッチしていることが分かる
どうするべきか?
まず最初にdevToolsのconsoleタブで $$('[role="presentation"]') と打ってみてセレクタの強度を確認しておきたい
この時点で14個ある
そもそもroleだから汎用的に使われるものなのでそれだけで目的のところにマッチするかはあやしい
コンテナ側の詳細度を上げていく
presentation周りの要素を見てみると、main, nav, そしていくつかのdata-testidがある
ツイッターではdata-testidを使うのは固有の値なのでけっこうおすすめではある(ただしidのように単一ではない)
まずは中央のタイムライン部分に絞り込んでおきたい。ただ main だけだと右サイドバーも含んでしまう。ここは[data-testid="primaryColumn"]を起点にするのがいいだろう
そしてpresentationの上にはnavもある。これも使えそうだ
では[data-testid="primaryColumn"] nav [data-testid="ScrollSnap-List"] でマッチさせたらどうだろうか?
絞り込まれたがまだ2つにマッチしてしまう。これは冒頭のスクリーンショットに挙げた2箇所となる
子要素の詳細度を上げていく
親要素側だけでは判別するのが難しいので、今度はpresentationの子要素側を見ていこう
上がヘッダ側、下がいまどうしてる?欄のpresentationになる
ここで大きく違うのは上はa要素で下はbutton要素を含んでいるところだろう
つまり、:has(a)で区別することが出来る
…と言いたいところだが、これもちょっと危うい気がする。他にa要素を持つpresentationが出てきたり、両者ともbuttonになりうるからだ
そこで着目したいのはaria-selectedの部分となる
このヘッダのタブは「おすすめ、フォロー中、(ピン留めされたリスト)」のどれかが選択されている状態になる。択一選択のタブリストであるため、aria-selectedがつくことになる
まとめると
つまり、[data-testid="primaryColumn"] nav [data-testid="ScrollSnap-List"] [role="presentation"]:has([aria-selected]):first-of-type とすると一つに絞り込める
まあここまでしなくても [data-testid="primaryColumn"] [role="presentation"]:has(a):first-of-type くらいでいいかもしれない
おわりに
今回のケースだと、親側を絞らなくても単に:has(a)をつければいいだけではあるけれど、ドキュメント全体からだと予測つかないところにマッチすることがあるので最低限絞り込んでおきたい
子要素側のマッチは有意に絞れることもあるし、無理やりな場合もある。ただUIの機能を考えることで意味的に絞り込むことができれば将来的に要素の変更があった場合にもセレクタを維持しやすくなるんじゃないかと思う
追記
よく見たらプロフ画面や通知画面のタブにもマッチしてしまっていた
やり直し
修正版
[data-testid="primaryColumn"] [role="presentation"]:has(a[href="/home"]):first-of-type
結局子要素のaタグで判別し、さらにhrefが/homeのものだけにした
これならおそらくhome画面だけなので大丈夫ではないだろうか
一昔前には:hasが無くて苦戦していたが、今はだいぶ楽になった
カスタムCSSの道は揺れ動くサイトに対して何通りも解法があるパズルなのでぜひ各人のエレガントな解を追求してみてほしい
追記2
そもそも「おすすめ」タブを非表示にしてもそれが選択されてる場合もあるのが気になった
なのでおすすめタブがaria-selected=trueだったら画面全体を赤くするなどして、選択を変更するように警告するstyleをつけるのがいいかもしれない