web-dev-qa-db-ja.com

親コンポーネントのCSSファイルから子コンポーネントをスタイルする方法

親コンポーネントがあります。

<parent></parent>

そして私はこのグループに子コンポーネントを追加したいと思います。

<parent>
  <child></child>
  <child></child>
  <child></child>
</parent>

親テンプレート:

<div class="parent">
  <!-- Children goes here -->
  <ng-content></ng-content>
</div>

子テンプレート:

<div class="child">Test</div>

parentchildは2つの別々のコンポーネントなので、それらのスタイルはそれぞれ独自の範囲に固定されています。

私の親コンポーネントで私がやってみました:

.parent .child {
  // Styles for child
}

しかし.childスタイルはchildコンポーネントには適用されていません。

スコープの問題を解決するためにstyleUrlsを使用してparentのスタイルシートをchildコンポーネントに含めることを試みました。

// child.component.ts
styleUrls: [
  './parent.component.css',
  './child.component.css',
]

しかし、それは役に立ちませんでした。また、childスタイルシートをparentにフェッチすることによって別の方法を試してみましたが、それはどちらも助けにはなりませんでした。

では、親コンポーネントに含まれる子コンポーネントをどのようにスタイル設定するのでしょうか。

180
Chrillewoodz

更新 - 最新の方法

あなたがそれを避けることができるならば、それをしないでください。 Devon Sansがコメントで指摘しているように、この機能はおそらく廃止されるでしょう。

更新 - 新しい方法

Angular 4.3.0 から、すべてのピアスcssコンビナータは非推奨になりました。 Angularチームは新しいコンビネータ::ng-deepを導入しました(それでも実験的なレベルであり、完全かつ最終的な方法ではありません)

デモ: https://plnkr.co/edit/RBJIszu14o4svHLQt563?p=preview

styles: [
    `
     :Host { color: red; }

     :Host ::ng-deep parent {
       color:blue;
     }
     :Host ::ng-deep child{
       color:orange;
     }
     :Host ::ng-deep child.class1 {
       color:yellow;
     }
     :Host ::ng-deep child.class2{
       color:pink;
     }
    `
],



template: `
      Angular2                                //red
      <parent>                                //blue
          <child></child>                     //orange
          <child class="class1"></child>      //yellow
          <child class="class2"></child>      //pink
      </parent>      
    `

古い道

encapsulation modepiercing CSS combinators >>>, /deep/ and ::shadowを使うことができます

実用例: http://plnkr.co/edit/1RBDGQ?p = preview

styles: [
    `
     :Host { color: red; }
     :Host >>> parent {
       color:blue;
     }
     :Host >>> child{
       color:orange;
     }
     :Host >>> child.class1 {
       color:yellow;
     }
     :Host >>> child.class2{
       color:pink;
     }
    `
    ],

template: `
  Angular2                                //red
  <parent>                                //blue
      <child></child>                     //orange
      <child class="class1"></child>      //yellow
      <child class="class2"></child>      //pink
  </parent>      
`
174
micronyks

更新3:

::ng-deepも非推奨になりました。つまり、これはもう行わないでください。これが、子コンポーネントのスタイルを親コンポーネントからオーバーライドする必要がある場合にどのように影響するかは不明です。ライブラリコンポーネントのスタイルをオーバーライドする必要がある場合、これがライブラリとしての動作にどのように影響するのかという理由で、これが完全に削除されると私には奇妙に思えますか?

これについて何か洞察がある場合はコメントしてください。

更新2:

/deep/と他のすべてのシャドーピアスセレクターは現在非推奨です。 Angularは::ng-deepを削除しました。これはより広い互換性のために代わりに使用されるべきです。

更新:

Angular-CLIを使用している場合、/deep/の代わりに>>>を使用する必要があります。そうしないと機能しません。

オリジナル:

Angular 2のGithubページに行き、 "style"をランダムに検索したところ、この質問が見つかりました。 Angular 2 - innerHTMLスタイル

これは2.0.0-beta.10>>>および::shadowセレクターに追加されたものを使用すると言っています。

(>>>)(と同等の/ deep /)と:: shadowが2.0.0-beta.10で追加されました。これらはshadow DOM CSSコンビネータ(非推奨)に似ており、カプセル化でのみ動作します:ViewEncapsulation.EmulatedこれはAngular 2のデフォルトです。それらはおそらくViewEncapsulation.Noneでも動作しますが、必要ないので無視されるだけです。クロスコンポーネントスタイリングのためのより高度な機能がサポートされるまで、これらのコンビネータは中間的な解決策にすぎません。

だから単純に:

:Host >>> .child {}

parentのスタイルシートファイルで問題を解決しました。上記の引用で述べたように、この解決策はより高度なクロスコンポーネントスタイリングがサポートされるまでの中間にすぎません。

48
Chrillewoodz

同じ問題を抱えていて、あなたがscss/sassでangular2-cliを使っているのであれば、 '>>>'の代わりに '/ deep /'を使ってください。

15
SergiySev

残念ながら、/ deep /セレクタは推奨されていません(少なくともChromeでは) https://www.chromestatus.com/features/6750456638341120

つまり、子コンポーネントに動的にスタイルを設定させる以外に、(現在)長期的な解決策はないようです。

あなたはあなたの子供にスタイルオブジェクトを渡してそれを以下のように適用させることができます。
<div [attr.style]="styleobject">

あるいは、あなたが特定のスタイルを持っているなら、あなたは以下のようなものを使うことができます。
<div [style.background-color]="colorvar">

これに関するこれ以上の議論: https://github.com/angular/angular /issues/6511

14
Matthew B.

実際の子コンポーネントにもっとターゲットを絞りたい場合は、次のようにします。これにより、他の子コンポーネントが同じクラス名を共有していても影響を受けません。

プランカー: https://plnkr.co/edit/ooBRp3ROk6fbWPuToytO?p=preview

例えば:

import {Component, NgModule } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>I'm the Host parent</h2>
      <child-component class="target1"></child-component><br/>
      <child-component class="target2"></child-component><br/>
      <child-component class="target3"></child-component><br/>
      <child-component class="target4"></child-component><br/>
      <child-component></child-component><br/>
    </div>
  `,
  styles: [`

  /deep/ child-component.target1 .child-box {
      color: red !important; 
      border: 10px solid red !important;
  }  

  /deep/ child-component.target2 .child-box {
      color: purple !important; 
      border: 10px solid purple !important;
  }  

  /deep/ child-component.target3 .child-box {
      color: orange !important; 
      border: 10px solid orange !important;
  }  

  /* this won't work because the target component is spelled incorrectly */
  /deep/ xxxxchild-component.target4 .child-box {
      color: orange !important; 
      border: 10px solid orange !important;
  }  

  /* this will affect any component that has a class name called .child-box */
  /deep/ .child-box {
      color: blue !important; 
      border: 10px solid blue !important;
  }  


  `]
})
export class App {
}

@Component({
  selector: 'child-component',
  template: `
    <div class="child-box">
      Child: This is some text in a box
    </div>
  `,
  styles: [`
    .child-box {
      color: green;    
      border: 1px solid green;
    }
  `]
})
export class ChildComponent {
}


@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, ChildComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

お役に立てれば!

codematrix

10
code5

:: ng-deepを使用したくない場合は、これを実行できますが、これは正しい方法のようです。

import { ViewEncapsulation } from '@angular/core';

@Component({
    ....
    encapsulation: ViewEncapsulation.None
})

そして、あなたは:: ng-deepから必要とせずにあなたのコンポーネントのCSSフォームを修正することができるでしょう。

.mat-sort-header-container {
  display:flex;
  justify-content:center;
}

警告:あなたのコンポーネントがたくさんの子を持っているかのように注意してください、あなたがこのコンポーネントのために書いたcssはすべての子供に影響を与えるかもしれません!

9
Tonio

Angularでこれを実現するにはいくつかのオプションがあります。

1)あなたはディープCSSセレクタを使用することができます

:Host >>> .childrens {
     color: red;
 }

2)デフォルトでEmulatedに設定されているビューのカプセル化を変更することもできますが、Shadow DOMのネイティブブラウザ実装を使用するNativeに簡単に変更することができます。

例えば、

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'parent',
  styles: [`
    .first {
      color:blue;
    }
    .second {
      color:red;
    }
 `],
 template: `
    <div>
      <child class="first">First</child>
      <child class="second">Second</child>
    </div>`,
  encapsulation: ViewEncapsulation.None,
 })
 export class ParentComponent  {
   constructor() {

   }
 }
6
Denis Rybalka

Angularコンポーネントは、外部の世界で利用可能なものを明示的に宣言する必要がある自己完結型のエンティティなので、親コンポーネント内の子コンポーネント要素に対するCSSルールを記述しないでください。子レイアウトが将来変更されると、その子コンポーネント要素のスタイルが他のコンポーネントのSCSSファイルに散らばって壊れやすくなり、スタイルが非常に壊れやすくなります。それがCSSの場合のViewEncapsulationの目的です。それ以外の場合は、オブジェクト指向プログラミングで他のクラスから特定のクラスのプライベートフィールドに値を代入できれば同じです。

したがって、やるべきことは、子Host要素に適用できるクラスのセットを定義し、子がそれらにどのように応答するかを実装することです。

技術的には、次のようにすることができます。

// child.component.html:
<span class="label-1"></span>

// child.component.scss:
:Host.child-color-black {
    .label-1 {
        color: black;
    }
}

:Host.child-color-blue {
    .label-1 {
        color: blue ;
    }
}

// parent.component.html:
<child class="child-color-black"></child>
<child class="child-color-blue"></child>

つまり、Angular + CSSクラスのセットによって提供される:Host疑似セレクタを使用して、子コンポーネント自体で可能な子スタイルを定義します。そうすれば、事前定義されたクラスを<child> Host要素に適用することによって、これらのスタイルを外部から起動することができます。

4

@INPUT変数を渡すほうがきれいです あなたが子コンポーネントコードにアクセスできるのなら:

アイデアは、親が子供にその外観の状態がどうあるべきかを伝え、子供がその状態をどのように表示するかを決定するというものです。それはいい建築です

SCSS方法:

.active {
  ::ng-deep md-list-item {
    background-color: #eee;
  }
}

より良い方法: - selected変数を使う:

<md-list>
    <a
            *ngFor="let convo of conversations"
            routerLink="/conversations/{{convo.id}}/messages"
            #rla="routerLinkActive"
            routerLinkActive="active">
        <app-conversation
                [selected]="rla.isActive"
                [convo]="convo"></app-conversation>
    </a>
</md-list>
4
robert king

実際にはもう1つ選択肢があります。どちらかといえば安全です。 ViewEncapsulation.Noneを使用できますが、すべてのコンポーネントスタイルをそのタグ(別名セレクタ)に配置できます。しかしとにかく、常に何らかのグローバルスタイルとカプセル化されたスタイルを好むのです。

これがDenis Rybalkaの変更例です。

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'parent',
  styles: [`
    parent {
      .first {
        color:blue;
      }
      .second {
        color:red;
      }
    }
 `],
 template: `
    <div>
      <child class="first">First</child>
      <child class="second">Second</child>
    </div>`,
  encapsulation: ViewEncapsulation.None,
})
export class ParentComponent  {
  constructor() { }
}
1
ilius33

私はまた、この問題を抱えていたので、廃止予定のソリューションを使用したくなかったので、次のようになりました。

親権で

 <dynamic-table
  ContainerCustomStyle='width: 400px;'
  >
 </dynamic-Table>

子コンポーネント

@Input() ContainerCustomStyle: string;

hTML divの子に

 <div class="container mat-elevation-z8"
 [style]='GetStyle(ContainerCustomStyle)' >

そしてコードで

constructor(private sanitizer: DomSanitizer) {  }

  GetStyle(c) {
    if (isNullOrUndefined(c)) { return null; }
    return  this.sanitizer.bypassSecurityTrustStyle(c);
  }

期待どおりに動作し、推奨されません。

1
d00lar

簡単な答えは、あなたがこれをするべきではないということです、まったく。それはコンポーネントのカプセル化を破り、自己完結型コンポーネントから得ている利益を損ないます。子コンポーネントにpropフラグを渡すことを検討してください。そうすれば、必要に応じて、レンダリング方法やCSSの適用方法を自分で決めることができます。

<parent>
  <child [foo]="bar"></child>
</parent>

Angularは、親から子供のスタイルに影響を与えるあらゆる方法を非推奨にしています。

https://angular.io/guide/component-styles#deprecated-deep-- and-ng-deep

1
Jed Richards

angular.io/guide/component-styles と述べているので、私はそれをより明確にするための例を提案する。

シャドーピアスの子孫コンビネータは廃止予定で、主要なブラウザやツールからサポートは削除されています。そのため、Angular(/ deep /、>>>、および:: ng-deepの3つすべて)のサポートを終了する予定です。それまでは:: ng-deepがツールとのより広い互換性のために好まれるべきです。

必要に応じてapp.component.scss*.scssをインポートしてください。 _colors.scssにはいくつかの一般的な色の値があります。

$button_ripple_red: #A41E34;
$button_ripple_white_text: #FFF;

すべてのコンポーネントにルールを適用します

btn-redクラスを持つすべてのボタンがスタイル設定されます。

@import `./theme/sass/_colors`;

// red background and white text
:Host /deep/ button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}

単一のコンポーネントにルールを適用する

btn-redコンポーネントのapp-loginクラスを持つすべてのボタンはスタイル設定されます。

@import `./theme/sass/_colors`;

/deep/ app-login button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}
0
AndreaM16