Svelte コンポーネントの <style> ブロック内で :global() 修飾子を使う
Svelte コンポーネントの <style>
ブロック内で使用できる :global()
修飾子の使い方について少しハマったのでメモです。
やりたいこと
Svelte コンポーネントでは特定のコンポーネント内の <style>
ブロック内で定義した CSS スタイルを他のコンポーネントに適用したり、そのコンポーネントの子孫コンポーネントに適用したりすることができる :global()
修飾子が用意されています。
例えば以下のような焼酎一覧を表示する ShochuList.svelte
というコンポーネントがあるとします。
このコンポーネントは以下の子コンポーネント Shochu.svelte
を参照しています。
ここで偶数行には背景色を指定したいと思います。Shochu.svelte
で
とすれば済む話ですが、本記事では :global()
修飾子の話がしたいので、ShochuList.svelte
にスタイルを指定したいと思います。
ShochuList.svelte
コンポーネント内の偶数番目の tr
に背景色を指定したいと思い、以下のように記述しました。
ところが以下のエラーが発生しました。
セレクターの位置に要素型セレクター (この場合 tr
) やユニバーサルセレクター ( *
) をいれるな、と言われています。
ちょっとよくわからなかったので色々試してみました。
:global()
の前のセレクターと引数のセレクターで考える
公式ドキュメントでは :global()
について多くは語られていませんが、もう一度眺めてみます。
すると前者の div :global(strong)
は普通に CSS で書く場合 div strong
を意図しており、後者の p:global(.red)
は p.red
を意図していることに気づき、:global()
修飾子の引数のセレクタによって、:global()
修飾子の前のセレクタとの間に結合子(結合子 - ウェブ開発を学ぶ | MDN)が必要なのではと気づきました。
従って上記公式ドキュメントの div :global(strong)
の div
と :global(strong)
の間のスペースは単なるスペースではなく、子孫結合子(結合子 - ウェブ開発を学ぶ | MDN)ということです。
試しに先ほどの ShochuList.svelte
のスタイルで tbody
と :global()
修飾子の間に子結合子(結合子 - ウェブ開発を学ぶ | MDN)を入れてみたところ、エラーが消え想定通り、偶数行に背景色が付きました。
これにより、:global()
修飾子は前のセレクターと引数のセレクターで、通常 CSS で書くときのことを意識すると正しくワークすることがわかりました。
様々なセレクターの組み合わせパターン
:global()
修飾子の使い方がわかりましたのでセレクタのパターンによる書き方を紹介します。(そんなの :global()
使って書かないだろみたいなのもありますが)
ID セレクター
クラスセレクター
属性セレクター
疑似クラス
できない書き方
試してみてできなかった書き方も紹介します。
global()
修飾子の前の結合子を引数には入れられない
先ほど 子結合子を付けて tbody>:global(tr:nth-of-type)
とすることでワークしたと書きましたが、試しにこの子結合子を global()
修飾子の引数に入れて tbody:global(>tr:nth-of-type)
としてみましたが、冒頭と同じエラーが出てダメでした。
global()
修飾子の前のセレクターとの結合子は前のセレクターと global()
修飾子の間に入れましょう。
global()
修飾子の引数内でセレクターリストは使えない
global()
修飾子の引数内だけでセレクターリスト使えたら便利だなと思い、table :global(th, td)
のように書いてみましたが、以下のエラーの通り、:global()
修飾子は一つのセレクターしか含められないとのことでした…。
あとがき
Svelte コンポーネント <style>
内での :global()
修飾子の使い方について調べてみました。わかれば当たり前のような気もするのですが、少しハマったので記事にしてみました。