我有一个父组件:

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

由于父组件和子组件是两个独立的组件,它们的样式被锁定在自己的范围内。

在我的父组件中,我尝试这样做:

.parent .child {
  // Styles for child
}

但是.child样式没有应用到子组件。

我尝试使用styleUrls将父组件的样式表包含到子组件中,以解决范围问题:

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

但这并没有帮助,我还尝试了另一种方法,将子样式表取到父样式表中,但这也没有帮助。

那么,如何样式包含在父组件中的子组件呢?


当前回答

更新-最新方式

如果可以避免,就不要做。正如Devon Sans在评论中指出的那样:这个功能很可能会被弃用。

最后一次更新

从Angular 4.3.0到现在(Angular 12.x),所有尖锐的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>      
    `

老方法

您可以使用封装模式和/或穿孔CSS组合符>>>,/deep/和::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>      
`

其他回答

截至目前(Angular 9), Angular使用Shadow DOM将组件显示为自定义HTML元素。为这些自定义元素设置样式的一种优雅方法可能是使用自定义CSS变量。下面是一个通用的例子:

class ChildElement extends HTMLElement { constructor() { super(); var shadow = this.attachShadow({mode: 'open'}); var wrapper = document.createElement('div'); wrapper.setAttribute('class', 'wrapper'); // Create some CSS to apply to the shadow dom var style = document.createElement('style'); style.textContent = ` /* Here we define the default value for the variable --background-clr */ :host { --background-clr: green; } .wrapper { width: 100px; height: 100px; background-color: var(--background-clr); border: 1px solid red; } `; shadow.appendChild(style); shadow.appendChild(wrapper); } } // Define the new element customElements.define('child-element', ChildElement); /* CSS CODE */ /* This element is referred as :host from the point of view of the custom element. Commenting out this CSS will result in the background to be green, as defined in the custom element */ child-element { --background-clr: yellow; } <div> <child-element></child-element> </div>

从上面的代码中可以看到,我们创建了一个自定义元素,就像Angular为每个组件所做的那样,然后我们从全局作用域覆盖自定义元素阴影根中的背景颜色变量。

在Angular应用中,这可能是这样的:

parent.component.scss

child-element {
  --background-clr: yellow;
}

child-element.component.scss

:host {
  --background-clr: green;
}

.wrapper {
  width: 100px;
  height: 100px;
  background-color: var(--background-clr);
  border: 1px solid red;
}

我也有这个问题,不想使用弃用的解决方案 所以我最后得出:

在parrent

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

子组件

@Input() ContainerCustomStyle: string;

在child In 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);
  }

作品像预期的那样,不应该被弃用;)

这是一个只有香草css的解决方案,没有什么花哨的,你甚至不需要!重要。我假设你不能修改子结点,否则答案就更简单了,我把答案放在最后以防万一。

当使用库中预先制作的组件时,有时需要覆盖子CSS,并且开发人员没有提供任何类输入变量。::ng-deep已弃用,encapsulation: ViewEncapsulation. jpgNone将使组件的所有CSS全局化。这里有一个简单的解决方案,这两个都不用。

事实上,我们确实需要一个全局样式,以便CSS到达子节点。我们可以把样式放到styles。CSS中或者我们可以创建一个新的CSS文件并把它添加到angular。json中的样式数组中。唯一的问题是我们需要一个特定的选择器,这样就不会针对其他元素。这是一个非常简单的解决方案-只需在html中添加一个唯一的类名,我建议在类名中使用父组件的名称,以确保它是唯一的。

父组件

<child class="child-in-parent-component"></child>

让我们假设我们想要改变child中所有按钮的背景颜色,我们确实需要实现正确的专一性以确保我们的样式优先。我们可以将!important放在所有属性的旁边,但更好的方法是重复类名,直到我们的选择器足够特定,这可能需要尝试几次。这样,其他人可以在必要时再次重写此css。

全局样式文件

.child-in-parent-component.child-in-parent-component.child-in-parent-component
  button {
  background-color: red;
}

或者用!important(不推荐)

.child-in-parent-component button {
  background-color: red !important;
}

如果子组件可以修改

只需向组件中添加一个输入变量,并使用Angular的ngStyle指令。您可以添加多个变量来为组件的多个区域设置样式。

子组件

type klass = { [prop: string]: any } | null;

@Component({...})
export class ChildComponent {
  @Input() containerClass: klass = null;
  @Input() pClass: klass = null;
...
}
<div [ngStyle]="containerClass">
  <p [ngStyle]="pClass">What color will I be?</p>
</div>

父组件

<child
  [containerClass]="{ padding: '20px', 'background-color': 'black' }"
  [pClass]="{ color: 'red' }"
>
</child>

这是创建具有动态样式的组件的预期方法。许多预制组件都有类似的输入变量。

随着互联网的更新,我想到了一个解决方案。

首先是一些警告。

还是不要这么做。澄清一下,我不打算让子组件允许您对它们进行样式设置。SOC。如果你作为组件设计者想要允许这一点,那么你就拥有了更多的权力。 如果你的孩子没有生活在阴影中,那么这对你来说就行不通了。 如果你必须支持一个浏览器,不能有一个影子dom,那么这也不会为你工作。

首先,将子组件的封装标记为shadow,以便它在实际的shadow dom中呈现。其次,将part属性添加到希望允许父元素设置样式的元素中。在父组件样式表中,可以使用::part()方法进行访问

实际上还有一个选择。这样比较安全。你可以使用ViewEncapsulation。但把你所有的组件样式放到它的标签(又名选择器)。但无论如何,总是喜欢一些全局风格加上封装风格。

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