コンポーネント テーマ
コンポーネント テーマを使用すると、グローバルに定義されたテーマを上書きして、特定のコンポーネント インスタンスのスタイルを変更できます。
概要
Ignite UI for Angular のコンポーネント テーマは CSS カスタム プロパティを使用します。各コンポーネントは構造的な CSS を独自のバンドルで提供し、Sass のテーマ関数と tokens() ミックスインは、その CSS で使用されるデザイン トークンの値を生成します。これにより、コンポーネントの CSS はツリー シェイキング可能になり、アプリケーションは構造的なルールを再生成することなく、ランタイムでテーマを上書きできます。
テーマの作成
コンポーネント テーマは 2 つのパーツで構成されます。
- コンポーネント テーマ関数 - 渡された値を正規化して、テーマ マップを返します。
tokens()ミックスイン - そのマップを使用して、グローバル モードまたはスコープ モードで CSS カスタム プロパティを出力します。
コンポーネントごとのラッパー ミックスインは、Ignite UI for Angular 22.1.0 以降では存在しません。すべてのコンポーネント テーマで tokens() を使用してください。
Tokens ミックスイン
モードによって、tokens() がユニバーサルな上書きを出力するか、コンポーネントの構造的なスタイルシートで使用される完全なローカル変数を出力するかが決まります。
グローバル モード (デフォルト) - ユニバーサル --ig-{component}-{property} トークンを出力します。ローカルの var() 参照は対応するグローバル トークンに書き換えられるため、派生値 (例: adaptive-contrast) はどのスコープでも正しく解決されます。サイズ可能な式は出力されないため、代わりに具体的な値を渡す必要があります。
// Input:
@include tokens(avatar-theme($background: red));
// Output:
:root {
--ig-avatar-background: red;
/* ... remaining avatar properties ... */
}
スコープ モード - コンポーネント ローカル変数 (--{property}) を出力します。フォールバック チェーンは、設定されたプレフィックス (--igx-*) からユニバーサル トークン (--ig-*)、最後にスキーマのデフォルト値の順になります。スタイルシートのルートから呼び出した場合は、テーマ マップのセレクターが使用されます。別のセレクター内から呼び出した場合は、現在のセレクターとコンポーネント セレクターに対して宣言が出力されます。
// Input (from root):
@include tokens(avatar-theme($background: red), $mode: 'scoped');
// Output:
igx-avatar {
--background: var(--igx-avatar-background, var(--ig-avatar-background, red));
/* ... remaining avatar properties ... */
}
// Input (from within a selector):
.my-theme {
@include tokens(avatar-theme($background: red), $mode: 'scoped');
}
// Output:
.my-theme,
.my-theme igx-avatar {
--background: var(--igx-avatar-background, var(--ig-avatar-background, red));
/* ... */
}
アプリケーション全体に適用する、または複数のコンポーネント インスタンスに継承させるユニバーサルな上書きには、デフォルトのグローバル モードを使用します。その場合、コンポーネントのローカル宣言がユニバーサル トークンを参照できるよう、コンポーネントをグローバルな theme() の出力に含めたままにしておく必要があります。
アバター テーマの定義:
// Change the background of the avatar to purple.
$avatar-purple-theme: avatar-theme(
$background: purple,
);
// Pass the theme to tokens() in its default global mode.
@include tokens($avatar-purple-theme);
上記のコードは、:root にユニバーサルな --ig-avatar-* の上書きを出力します。その後にアバターを対象とする別のグローバルな tokens() 呼び出しがあると、通常のカスケード順序に従って後の値が優先されます。
次に例を示します。
// ...
@include tokens($avatar-purple-theme);
// Later
$avatar-royalblue-theme: avatar-theme(
$background: royalblue,
);
@include tokens($avatar-royalblue-theme);
上記のコードでは、それ以前にインクルードされた tokens ミックスインがすべて上書きされるため、事実上のグローバル テーマは $avatar-royalblue-theme になります。
$mode: 'scoped' は、グローバル テーマでは提供されないコンポーネント ローカル宣言を出力する必要がある場合にのみ使用してください。代表的なケースは、theme() から除外されているコンポーネント、コンポーネント ローカルのサイズ式、複数のセレクターにローカル宣言が必要なテーマ マップ、異なるスキーマやライト/ダーク バリアントを定義するテーマです。最後のケースでは、そのバリアントの $schema をコンポーネント テーマ関数に渡してください。
tokens() がセレクター内にネストされている、または css-vars() 呼び出しを置き換えるという理由だけで、スコープ モードを選択しないでください。コンポーネントがグローバルな theme() の出力に含まれたままであれば、通常はデフォルトのグローバル モードでも、ユニバーサル トークンのフォールバック チェーンによって意図した上書きが適用されます。スコープ モードは、カスタマイズがデフォルト モードでは出力されない宣言を必要とすることを確認したうえで使用してください。
デタッチされたオーバーレイは、それを開いたコンポーネントからトークンの上書きを継承しません。上書きをグローバルに出力するか、アウトレットをテーマが適用されたコンテナーの下に移動してください。オーバーレイのカスタマイズに、グローバル テーマでは提供されないコンポーネント ローカル宣言も必要な場合にのみ、スコープ モードを使用してください。オーバーレイ スタイリングを参照してください。
テーマのスコープ
前の例で見たように、同じコンポーネントをターゲットにした複数のテーマを同じレベルに追加すると、最後のテーマ ミックスインが優先されます。これは CSS のカスケードの仕組みによるものです。同じ種類のコンポーネントをターゲットにした 2 つ以上のテーマが必要な場合は、それぞれをセレクターにスコープする必要があります。たとえば、複数の igx-avatar テーマを作成して特定の CSS セレクターにスコープし、それらのセレクターをコンポーネントのマークアップで使用できます。
// ...
// CSS class selectors
.avatar-royalblue {
@include tokens($avatar-royalblue-theme);
}
.avatar-purple {
@include tokens($avatar-purple-theme);
}
コンポーネント テンプレート:
<div class="avatar-royalblue">
<igx-avatar initials="AZ"></igx-avatar>
</div>
<div class="avatar-purple">
<igx-avatar icon="home"></igx-avatar>
</div>
カスケード レイヤー
構造的なスタイル、デザイン システムの上書き、派生/コンテキスト トークンは、コンポーネント バンドルとグローバル プリセットに分割されています。Ignite UI はこれらを、ig.reset → ig.base → ig.material/ig.bootstrap/ig.fluent/ig.indigo → ig.derived の順序のカスケード レイヤーで宣言しています。バンドルの読み込み順序に関係なく、後のレイヤーが前のレイヤーより優先されます。
サードパーティ製のリセット用またはノーマライズ用のスタイルシートは、コンポーネントやタイポグラフィのスタイルを上書きしないよう、ig.reset でラップしてください。
@layer ig.reset {
@import "minireset.css";
}
どのレイヤーにも属さないアプリケーションのルールは、レイヤー内にある Ignite UI のルールより優先されます。Ignite UI のレイヤー順序に意図的に組み込みたい場合を除き、アプリケーションでの通常の上書きはレイヤーに含めないでください。
表示のカプセル化
ここまでは、グローバルにスコープされ、単一の Sass ファイルに含まれるテーマを作成する方法を説明しました。ただし、これが常に望ましいとは限らず、Sass ファイルを特定のコンポーネントにバインドしたい場合もあります。その場合は、表示のカプセル化、特に Angular でそれがどのようにエミュレートされるかを考慮する必要があります。
Angular では、表示のカプセル化に Emulated (デフォルト)、ShadowDom、None の 3 つの方法を採用しています。各方法の詳細については、Angular ドキュメントをご覧ください。ここでは、表示がカプセル化された親コンポーネント内にある Ignite UI for Angular コンポーネントのテーマを設定する方法を詳しく見ていきます。
そもそも Emulated の表示のカプセル化とは何でしょうか。このタイプの表示のカプセル化は Shadow DOM 仕様を利用せず、ホスト要素に適用される一意の属性識別子を使用して、コンポーネントとその子のスタイルをバインドします。
CSS 変数を使用した例を見てみましょう。特定の親コンポーネントにバインドされたアバター テーマを作成します。
以下はシンプルなコンポーネントです。
import { Component, Input } from "@angular/core";
@Component({
selector: "app-avatar",
styleUrls: ["./app-avatar.component.scss"],
template: `<igx-avatar [initials]="initials"></igx-avatar>`,
})
export class AvatarComponent extends Component {
@Input() public initials = "AZ";
}
Sass スタイルシートは次のようになります。
// app-avatar.component.scss
// Import the theming module
@use "igniteui-angular/theming" as *;
// !IMPORTANT: Prior to Ignite UI for Angular version 13 use:
// @import '~igniteui-angular/lib/core/styles/themes/index';
$avatar-royalblue-theme: avatar-theme(
$background: royalblue,
);
:host {
@include tokens($avatar-royalblue-theme);
}
ユニバーサルなアバター トークンはこのホストで宣言され、その中のアバターに継承されます。ただし、Angular が生成するカプセル化属性により、より複雑なコンポーネント テーマが出力するセレクターが、ネストされた要素や内部要素に一致しない場合があります。ローカル テーマが有効にならない場合は、その @include を ::ng-deep で囲むか、グローバル スタイルシートに移動してください。グローバルに出力しない限り、テーマはこの app-avatar サブツリーに限定されます。
Shadow DOM の境界を越える場合や、デタッチされたオーバーレイ アウトレットの場合は、対象がテーマを継承できる場所、またはテーマのセレクターが一致する場所でテーマを出力する必要があります。
上記の例は、Sass を使用せずに実現することもできます。--ig-avatar-background CSS 変数に目的の色を設定するだけです。
/* app-avatar.component.css */
:host {
--ig-avatar-background: royalblue;
}
API の概要
その他のリソース
グローバル テーマの設定方法:
コミュニティに参加して新しいアイデアをご提案ください。