※ng-deep は非推奨です!!!
最初に念を押しておくがng-deepは非推奨である。どんどん使おうという記事ではないのでご留意を。
Angular 公式ドキュメントより:(非推奨) /deep/ 、 >>> と ::ng-deep
2024/09/17 new! → Angular 公式ドキュメントより:::ng-deep
何がどう非推奨とか、どうすればよいとかはまた別のお話なのでここでは触れません。
本題
非推奨とはいえ、使わざるを得ない場面で致し方なく…というものにはng-deepをくっつけて実装してある。なので、一応その仕様について一発で分かるようにまとめておく備忘録を残す。
通常の状態
これは適当に作ったシンプルなAngular プロジェクトで、とりあえず各種コンポーネントにあるCSSでlabelのcolor指定をしたもの。まだng-deepは使用していない状態。
孫コンポーネント Yに「::ng-deep」を適用してみる
最下層までさかのぼってlabelの色が全て緑になった。公式に書いてある通りの挙動を確認できた。
擬似クラス ::ng-deep を任意の CSS ルールに適用すると、そのルールに対するビューのカプセル化が 完全に無効になります。また、::ng-deep が適用されたすべてのスタイルは、グローバルなスタイルになります。
孫コンポーネント Yに「:host ::ng-deep」を適用してみる
公式の文章の続き。:host を追加するとそのコンポーネントにしか適用されないようになった。
指定されたスタイルを 現在のコンポーネントとそのすべての子孫に適用するには、必ず ::ng-deep の前に :host セレクターを含めるように してください。
子コンポーネント Aに「:host ::ng-deep」を適用してみる
すべての子孫に適用する
とある。どういうことか確認するため、今度は子コンポーネントAに適用すると…
このように孫コンポーネントXにも波及する。
孫に波及されると困る場合
と、このように「:host ::ng-deep」を使えば子孫までCSSを反映できる。Angular Materialなどのモジュールで生成されるUIに対してCSSを適用したい場合などに使うものと思う。
ただ、子コンポーネント内の子孫には反映してほしいけど、孫コンポーネントまで波及されると困る…という場合もあると思う。その場合は指定条件を増やせばよい。まぁこれはAngular のっていうか普通にCSS の基本だけど…普段意識してないと案外忘れがち。
例えば、<label class="my-label">
というようにclass指定をすることで、孫には反映させない(※正確には、孫に"my-label"クラス指定を使わないことで適用外にする)ようにできる。
まとめ
- ::ng-deep はカプセル化を無視してグローバルなスタイルとして適用される
- :host ::ng-deep にすることで自分とその子孫へのスタイルとして適用される
- 子孫への影響を抑えたい場合は指定条件を厳しくしておく
2024/09/17 追記:ng-deep の代替について
リンクが死んでたので新しいドキュメントのリンク先に更新しました。ついでにng-deep の正式な代替案みたいなものが出てるか軽く調べたんですが、まだ活発に議論されてました。まぁAngular の!important
みたいなもんだし、使わないのが一番だけど、じゃあこれが無くなったらどうすんねん!についてはまだ答えが出てない模様…
https://github.com/angular/angular/issues/25160