如何从父组件的CSS文件设置子组件的样式?

问题描述 投票:188回答:13

我有一个父组件:

<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组件。

我尝试使用styleUrlsparent的样式表包含到child组件中以解决范围问题:

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

但这没有帮助,也尝试了另一种方式将child样式表提取到parent,但这也没有帮助。

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

css angular angular-components
13个回答
183
投票

Update - Newest Way

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

Update - Newer Way

从Angular 4.3.0开始,所有穿孔的css组合器都被弃用了。 Angular团队推出了一个新的组合子::ng-deep(仍处于实验水平,而不是完整和最终的方式),如下所示,

但是:ぁzxswい

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


Old way

你可以使用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

2
投票

实际上还有一个选择。这是相当安全的。您可以使用ViewEncapsulation.None但是将所有组件样式放入其标记(也称为选择器)。但无论如何总是喜欢一些全局风格加封装样式。

这里修改了Denis Rybalka的例子:

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

1
投票

答案很简单,你根本就不应该这样做。它打破了组件封装并破坏了从自包含组件中获得的好处。考虑将prop标志传递给子组件,然后可以根据需要决定自己如何以不同方式呈现或应用不同的CSS。

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

Angular正在弃用影响父母子女风格的所有方式。

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


1
投票

我也有这个问题,并不想使用已弃用的解决方案,所以我最终得到:

在父母

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

子组件

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

在html div的孩子

@Input() ContainerCustomStyle: string;

并在代码中

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

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


0
投票

我提出了一个例子来说明这一点,因为constructor(private sanitizer: DomSanitizer) { } GetStyle(c) { if (isNullOrUndefined(c)) { return null; } return this.sanitizer.bypassSecurityTrustStyle(c); } 说:

不推荐使用阴影穿透后代组合器,并且正在从主要浏览器和工具中删除支持。因此,我们计划放弃Angular中的支持(对于/ deep /,>>>和:: ng-deep的所有3个)。在此之前:: ng-deep应该是首选,以便与工具更广泛地兼容。

angular.io/guide/component-styles,如果需要,导入你的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

48
投票

更新3:

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> ` 也被弃用了,这意味着你不应该再这样做了。目前还不清楚这会如何影响您需要从父组件覆盖子组件中的样式的内容。对我而言,如果完全删除它似乎很奇怪,因为这会影响作为库需要覆盖库组件中的样式的库?

如果您对此有任何见解,请发表评论。

更新2:

由于::ng-deep和所有其他阴影穿孔选择器现已弃用。角度下降/deep/应该用来代替更广泛的兼容性。

更新:

如果使用Angular-CLI,您需要使用::ng-deep而不是/deep/,否则它将无法工作。

原版的:

在访问Angular2的Github页面并随机搜索“样式”后,我发现了这个问题:>>>

据说使用在Angular 2 - innerHTML styling2.0.0-beta.10>>>选择器中添加的东西。

(>>>)(和等效/深/)和:: shadow在2.0.0-beta.10中添加。它们类似于shadow DOM CSS组合器(不推荐使用),仅适用于封装:ViewEncapsulation.Emulated,这是Angular2中的默认值。它们可能也适用于ViewEncapsulation.None但只是被忽略,因为它们不是必需的。在支持跨组件样式的更高级功能之前,这些组合器只是一种中间解决方案。

所以简单地做:

::shadow

:host >>> .child {} 的样式表文件中解决了这个问题。请注意,如上面引用中所述,此解决方案仅在支持更高级的跨组件样式之前才是中间的。


15
投票

有同样的问题,所以如果你使用angular2-cli和scss / sass使用'/ deep /'而不是'>>>',那么最后的选择器还不支持(但是对css很有用)。


14
投票

可悲的是,/ deep / selector似乎已被弃用(至少在Chrome中)parent

简而言之,似乎(目前)没有长期解决方案,除了以某种方式让您的子组件动态地设置事物。 您可以将样式对象传递给您的孩子并通过以下方式应用它: https://www.chromestatus.com/features/6750456638341120 或者,如果您有特定的风格,您可以使用以下内容: <div [attr.style]="styleobject">

更多与此有关的讨论:<div [style.background-color]="colorvar">


10
投票

如果您希望更多地针对实际的子组件而不是您应该执行的操作。这样,如果其他子组件共享相同的类名,则不会受到影响。

Plunker:https://github.com/angular/angular/issues/6511

例如:

https://plnkr.co/edit/ooBRp3ROk6fbWPuToytO?p=preview

希望这可以帮助!

codematrix


9
投票

如果你不想使用:: ng-deep,你可以这样做,这似乎是正确的方法:

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

然后,您将能够在不需要:: ng-deep的情况下修改组件的css

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

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

警告:小心你的组件有很多孩子,你为这个组件编写的CSS可能会影响所有孩子!


7
投票

在Angular中有几个选项可以实现:

1)您可以使用深度css选择器

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

2)你也可以将它设置为Emulated的视图封装更改为默认设置,但可以很容易地更改为使用Shadow DOM本机浏览器实现的Native,在你的情况下你只需要禁用它

例如:`

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

5
投票

您不应该为父组件中的子组件元素编写CSS规则,因为Angular组件是一个自包含的实体,应该明确声明可用于外部世界的内容。如果子布局将来发生变化,那么分散在其他组件的SCSS文件中的子组件元素的样式很容易破坏,从而使您的样式非常脆弱。这就是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() { } } 在CSS的情况下的用途。否则,如果您可以从面向对象编程中的任何其他类为某些类的私有字段赋值,那么它将是相同的。

因此,您应该做的是定义一组可以应用于子宿主元素的类,并实现子代对它们的响应方式。

从技术上讲,它可以如下完成:

ViewEncapsulation

换句话说,您使用Angular + CSS类集提供的// 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> 伪选择器来定义子组件本身中可能的子样式。然后,您可以通过将预定义的类应用于:host主机元素来从外部触发这些样式。


4
投票

如果您有权访问子组件代码,我发现传递@INPUT变量要清晰得多:

这个想法是父母告诉孩子它的外貌应该是什么,孩子决定如何显示状态。这是一个很好的建筑

SCSS方式:

<child>

更好的方法: - 使用.active { ::ng-deep md-list-item { background-color: #eee; } } 变量:

selected
© www.soinside.com 2019 - 2024. All rights reserved.