IT story

부모 구성 요소의 CSS 파일에서 자식 구성 요소의 스타일을 지정하는 방법은 무엇입니까?

hot-time 2020. 5. 5. 19:37
반응형

부모 구성 요소의 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두 개의 별도 구성 요소, 자신의 스타일이 자신의 범위에 잠겨 있습니다.

부모 구성 요소에서 다음을 시도했습니다.

.parent .child {
  // Styles for child
}

그러나 .child스타일은 child구성 요소에 적용되지 않습니다 .

범위 문제를 해결하기 위해 의 스타일 시트를 구성 요소 styleUrls에 포함시키는 데 사용하려고했습니다 .parentchild

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

그러나 그것은 도움이되지 않았으며 child스타일 시트를 가져 와서 다른 방법으로 시도했지만 parent도움이되지 못했습니다.

부모 구성 요소에 포함 된 하위 구성 요소를 어떻게 스타일링합니까?


업데이트-최신 방법

피할 수 있다면하지 마십시오. 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 mode및 / 또는piercing 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>      
`

업데이트 3 :

::ng-deep더 이상 사용하지 않아야 함을 의미합니다. 이것이 부모 구성 요소에서 자식 구성 요소의 스타일을 재정의해야하는 항목에 어떤 영향을 미치는지 확실하지 않습니다. 라이브러리 구성 요소에서 스타일을 재정의 해야하는 라이브러리에 영향을 미치기 때문에 이것이 완전히 제거되면 이상하게 보입니다.

이것에 대한 통찰력이 있으면 의견을 말하십시오.

업데이트 2 :

이후 /deep/다른 모든 섀도우 피어싱 선택기는 더 이상 사용되지 않습니다. ::ng-deep더 넓은 호환성을 위해 대신 사용해야하는 앵귤러 드롭 .

최신 정보:

Angular-CLI를 사용 /deep/하는 경우 대신 사용해야 >>>합니다. 그렇지 않으면 작동하지 않습니다.

기발한:

Angular2의 Github 페이지로 이동하여 "style"에 대한 임의 검색을 수행 한 후 Angular 2-innerHTML styling

어떤이 추가 된 것을 사용하는 것이 말했다 2.0.0-beta.10>>>::shadow선택기.

(>>>) (및 동등한 / deep /) 및 :: shadow가 2.0.0-beta.10에 추가되었습니다. 이들은 그림자 DOM CSS 결합기 (더 이상 사용되지 않음)와 유사하며 Angular2의 기본값 인 캡슐화 : ViewEncapsulation.Emulated에서만 작동합니다. 아마도 ViewEncapsulation에서도 작동하지만 필요하지 않기 때문에 무시됩니다. 이 컴비 네이터는 교차 컴포넌트 스타일링을위한 고급 기능이 지원 될 때까지 중간 솔루션입니다.

간단히 말해서 :

:host >>> .child {}

에서 parent의 스타일 시트 파일 문제를 해결했다. 위 인용문에 명시된 바와 같이이 솔루션은 고급 교차 컴포넌트 스타일링이 지원 될 때까지 중간 수준입니다.


같은 문제가 있었으므로 scss / sass와 함께 angular2-cli를 사용하는 경우 '>>>'대신 '/ deep /'을 사용하면 마지막 선택기가 아직 지원되지 않습니다 (그러나 CSS에서는 훌륭하게 작동합니다).


슬프게도 / deep / 선택기가 더 이상 사용되지 않는 것으로 보입니다 (적어도 Chrome에서는) https://www.chromestatus.com/features/6750456638341120

요컨대, 자식 컴포넌트가 동적으로 스타일을 지정하는 것 외에는 (현재) 장기적인 해결책이없는 것으로 보입니다.

자녀에게 스타일 객체를 전달하고 다음을 통해 적용
<div [attr.style]="styleobject">

할 수 있습니다 . 또는 특정 스타일이있는 경우 다음과 같은 것을 사용할 수 있습니다.
<div [style.background-color]="colorvar">

이것과 관련된 추가 토론 : https://github.com/angular/angular/issues/6511


:: ng-deep을 사용하지 않으려면 올바른 방법으로 보일 수 있습니다.

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

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

그런 다음 :: ng-deep 없이도 구성 요소에서 CSS를 수정할 수 있습니다.

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

경고 : 구성 요소에 많은 자식이있는 경우이 구성 요소에 대해 작성한 CSS가 모든 자식에 영향을 줄 수 있으므로주의하십시오!


실제 하위 구성 요소를보다 잘 타겟팅하려면 다음을 수행해야합니다. 이런 식으로 다른 자식 구성 요소가 동일한 클래스 이름을 공유하면 영향을받지 않습니다.

플 런커 : 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 {}

도움이 되었기를 바랍니다!

코드 매트릭스


Angular에서는이를 수행 할 수있는 몇 가지 옵션이 있습니다.

1) 깊은 CSS 선택기를 사용할 수 있습니다

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

2) 뷰 캡슐화를 기본값으로 에뮬레이트로 설정했지만 Shadow DOM 기본 브라우저 구현을 사용하는 네이티브로 쉽게 변경할 수 있습니다.이 경우 비활성화해야합니다.

예를 들면 :

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() {

   }
 }

Angular 구성 요소는 외부 세계에서 사용할 수있는 항목을 명시 적으로 선언해야하는 독립적 인 엔터티이므로 부모 구성 요소의 자식 구성 요소에 대한 CSS 규칙을 작성해서는 안됩니다. 나중에 자식 레이아웃이 변경되면 다른 구성 요소의 SCSS 파일에 흩어져있는 해당 자식 구성 요소의 스타일이 쉽게 깨져서 스타일이 매우 약해질 수 있습니다. 이것이 ViewEncapsulationCSS의 경우입니다. 그렇지 않으면 객체 지향 프로그래밍의 다른 클래스에서 일부 클래스의 개인 필드에 값을 할당 할 수 있다면 동일합니다.

따라서해야 할 일은 자식 호스트 요소에 적용 할 수있는 클래스 집합을 정의하고 자식이 이에 응답하는 방식을 구현하는 것입니다.

기술적으로 다음과 같이 수행 할 수 있습니다.

// 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>

In other words, you use :host pseudo-selector provided by Angular + set of CSS classes to define possible child styles in child component itself. You then have the ability to trigger those styles from outside by applying pre-defined classes to the <child> host element.


I find it a lot cleaner to pass an @INPUT variable if you have access to the child component code:

The idea is that the parent tells the child what its state of appearance should be, and the child decides how to display the state. It's a nice architecture

SCSS Way:

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

Better way: - use selected variable:

<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>

Actually there is one more option. Which is rather safe. You can use ViewEncapsulation.None BUT put all your component styles into its tag (aka selector). But anyway always prefer some global style plus encapsulated styles.

Here is modified Denis Rybalka example:

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() { }
}

The quick answer is you shouldn't be doing this, at all. It breaks component encapsulation and undermines the benefit you're getting from self-contained components. Consider passing a prop flag to the child component, it can then decide itself how to render differently or apply different CSS, if necessary.

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

Angular is deprecating all ways of affecting child styles from parents.

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


i also had this problem and didnt wanted to use deprecated solution so i ended up with:

in parrent

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

child component

@Input() ContainerCustomStyle: string;

in child in html div

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

and in code

constructor(private sanitizer: DomSanitizer) {  }

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

works like expected and should not be deprecated ;)


I propose an example to make it more clear, since angular.io/guide/component-styles states:

The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.

On app.component.scss, import your *.scss if needed. _colors.scss has some common color values:

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

Apply a rule to all components

All the buttons having btn-red class will be styled.

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

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

Apply a rule to a single component

All the buttons having btn-red class on app-login component will be styled.

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

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

I have solved it outside Angular. I have defined a shared scss that I'm importing to my children.

shared.scss

%cell {
  color: #333333;
  background: #eee;
  font-size: 13px;
  font-weight: 600;
}

child.scss

@import 'styles.scss';
.cell {
  @extend %cell;
}

My proposed approach is a way how to solve the problem the OP has asked about. As mentioned at multiple occasions, ::ng-deep, :ng-host will get depreciated and disabling encapsulation is just too much of a code leakage, in my view.

참고URL : https://stackoverflow.com/questions/36527605/how-to-style-child-components-from-parent-components-css-file

반응형