CSSシャドウパーツ
CSS シャドウパーツを使用すると、開発者はシャドウツリー内の要素のCSSプロパティをスタイルできます。これは、Ionic FrameworkのShadow DOMコンポーネントをカスタマイズする際に非常に役立ちます。
なぜシャドウパーツなのか?
Ionic Frameworkは、Web Componentsの分散セットです。Web Componentsは、スタイルとマークアップをカプセル化するために、Shadow DOM仕様に従います。
Ionic Frameworkのコンポーネントは、すべてがShadow DOMコンポーネントではありません。コンポーネントがShadow DOMコンポーネントである場合、そのコンポーネントドキュメントの右上隅にバッジが表示されます。Shadow DOMコンポーネントの例として、ボタンコンポーネントがあります。
Shadow DOMは、スタイルがコンポーネントから漏れ出し、意図せずに他の要素に適用されるのを防ぐのに役立ちます。たとえば、ion-button
コンポーネントに.button
クラスを割り当てます。Shadow DOMのカプセル化がない場合、ユーザーが独自の要素のいずれかにクラス.button
を設定すると、Ionic Frameworkのボタンのスタイルを継承します。ion-button
はシャドウコンポーネントであるため、これは問題になりません。
ただし、このカプセル化により、スタイルはシャドウコンポーネントの内部要素にも浸透できません。つまり、シャドウコンポーネントがシャドウツリー内に要素をレンダリングする場合、内部要素はCSSで直接ターゲットにできません。ion-select
コンポーネントを例として使用すると、次のマークアップがレンダリングされます。
<ion-select>
#shadow-root
<div class="select-text select-placeholder"></div>
<div class="select-icon"></div>
</ion-select>
プレースホルダーテキストとアイコン要素は#shadow-root
の内側にあるため、次のCSSはプレースホルダーをスタイルするために機能しません。
/* Does NOT work */
ion-select .select-placeholder {
color: blue;
}
では、どうすればこれを解決できるでしょうか?CSSシャドウパーツです!
シャドウパーツの説明
シャドウパーツを使用すると、開発者はシャドウツリーの外側からシャドウツリー内部をスタイルできます。そのためには、パーツを公開する必要があり、その後、::partを使用してスタイルを設定できます。
パーツの公開
シャドウDOMコンポーネントを作成するとき、要素にpart
属性を割り当てることにより、シャドウツリー内の要素にパーツを追加できます。これはIonic Frameworkのコンポーネントに追加されており、エンドユーザーからのアクションは必要ありません。
引き続きion-select
コンポーネントを例として使用すると、マークアップは次のようになります。
<ion-select>
#shadow-root
<div part="placeholder" class="select-text select-placeholder"></div>
<div part="icon" class="select-icon"></div>
</ion-select>
上記は、placeholder
とicon
の2つのパーツを示しています。すべてのパーツについては、selectドキュメントを参照してください。
これらのパーツが公開されると、::partを使用して要素を直接スタイル設定できるようになります。
::partの仕組み
::part()
擬似要素を使用すると、開発者はpart属性を介して公開されたシャドウツリー内の要素を選択できます。
ion-select
が値が選択されていない場合のテキストをスタイルするためにplaceholder
パーツを公開していることがわかっているので、次の方法でカスタマイズできます。
ion-select::part(placeholder) {
color: blue;
opacity: 1;
}
::part
を使用したスタイリングでは、その要素に受け入れられる任意のCSSプロパティを変更できます。
パーツをターゲットにできることに加えて、擬似要素は明示的に公開されていなくてもスタイル設定できます。
ion-select::part(placeholder)::first-letter {
font-size: 22px;
font-weight: 500;
}
パーツは、ほとんどの擬似クラスでも機能します。
ion-item::part(native):hover {
color: green;
}
ベンダープレフィックス付きの擬似要素および構造擬似クラスには、いくつかの既知の制限事項があります。
Ionic Frameworkのパーツ
Ionic Frameworkコンポーネント用に公開されたすべてのパーツは、APIページの「CSS シャドウパーツ」の見出しの下にあります。すべてのコンポーネントとそのAPIページを表示するには、コンポーネントドキュメントを参照してください。
パーツを持たせるためには、コンポーネントは次の基準を満たす必要があります。
- それは、Shadow DOMコンポーネントです。スコープ付きまたはLight DOMコンポーネントの場合、子要素を直接ターゲットにできます。コンポーネントがスコープ付きまたはシャドウである場合、コンポーネントドキュメントページにその名前でリストされます。
- 子要素が含まれています。たとえば、
ion-card-header
はシャドウコンポーネントですが、すべてのスタイルはホスト要素に適用されます。子要素がないため、パーツは必要ありません。 - 子要素は構造的ではありません。
ion-title
を含む特定のコンポーネントでは、子要素は内部要素を配置するために使用される構造要素です。予期しない結果を招く可能性があるため、構造要素をカスタマイズすることはお勧めしません。
追加パーツに関する推奨事項を歓迎します。パーツをリクエストするときは、できるだけ多くの情報を記載した新しいGitHub issueを作成してください。
既知の制限事項
ブラウザサポート
CSSシャドウパーツは、すべての主要なブラウザの最新バージョンでサポートされています。ただし、古いバージョンの一部では、シャドウパーツをサポートしていません。アプリにパーツを実装する前に、ブラウザサポートが要件を満たしていることを確認してください。古いバージョンのブラウザサポートが必要な場合は、スタイリングにCSS変数を使用し続けることをお勧めします。
ベンダープレフィックス付き擬似要素
擬似要素は現時点ではサポートされていません。この例としては、::-webkit-scrollbar
擬似要素などが挙げられます。
/* Does NOT work */
my-component::part(scroll)::-webkit-scrollbar {
background: green;
}
詳細については、GitHub のこの issue を参照してください。
構造擬似クラス
ほとんどの擬似クラスは parts でサポートされていますが、構造擬似クラス はサポートされていません。動作しない構造擬似クラスの例を以下に示します。
/* Does NOT work */
my-component::part(container):first-child {
background: green;
}
/* Does NOT work */
my-component::part(container):last-child {
background: green;
}
パーツのチェーン
::part()
擬似要素は、追加の ::part()
と一致させることはできません。
例えば、my-component::part(button)::part(label)
は何も一致させません。これは、このようにすることで、意図されているよりも多くの構造情報が公開されてしまうためです。
<my-component>
の内部のボタンが、part="label => button-label"
のようにして、ボタンの内部パーツをパネル自身の part 要素マップに転送している場合、my-component::part(button-label)
のようなセレクターは、他のラベルを無視して、その 1 つのボタンのラベルだけを選択します。