Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to style child components from parent component's CSS file?

I've got a parent component:

<parent></parent>

And I want to populate this group with child components:

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

Parent template:

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

Child template:

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

Since parent and child are two separate components, their styles are locked to their own scope.

In my parent component I tried doing:

.parent .child {
  // Styles for child
}

But the .child styles are not getting applied to the child components.

I tried using styleUrls to include the parent's stylesheet into child component to solve the scope issue:

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

But that didn't help, also tried the other way by fetching the child stylesheet into parent but that didn't help either.

So how do you style child components that are included into a parent component?

like image 754
Chrillewoodz Avatar asked Apr 10 '16 08:04

Chrillewoodz


People also ask

How do you style a child component from the parent component?

We can use the :host pseudo-selector to combine a set of CSS classes to define possible child styles inside the child component itself. And then we can trigger these classes from outside by applying the style we want to the <child> host element. Angular provides a way to bind a single css class to an host element.

How do I apply CSS from parent to child?

It's easy to apply style to a child element, but if you want to apply style to a parent class that already has child elements, you can use the CSS selector child combinators (>), which are placed between two CSS selectors. For example, div > p selects all <p> elements where the parent is a <div> element.

Is it possible for a child component to inherit styles CSS from a parent component?

You should not write CSS rules for a child component elements in a parent component, since an Angular component is a self-contained entity which should explicitly declare what is available for the outside world.

How do you send value from parent to child component?

Sending data to a child componentlinkThe @Input() decorator in a child component or directive signifies that the property can receive its value from its parent component. To use @Input() , you must configure the parent and child.


3 Answers

Update - Newest Way

Don't do it, if you can avoid it. As Devon Sans points out in the comments: This feature will most likely be deprecated.

Last Update

From Angular 4.3.0 till even now (Angular 12.x), all piercing css combinators were deprecated. Angular team introduced a new combinator ::ng-deep as shown below,

DEMO : 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>      
    `

Old way

You can use encapsulation mode and/or piercing CSS combinators >>>, /deep/ and ::shadow

working example : 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>      
`
like image 114
Nikhil Shah Avatar answered Oct 07 '22 21:10

Nikhil Shah


You should NOT use ::ng-deep, it is deprecated. In Angular, the proper way to change the style of children's component from the parent is to use encapsulation (read the warning below to understand the implications):

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

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

And then, you will be able to modify the css form your component without a need from ::ng-deep

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

WARNING: Doing this will make all css rules you write for this component to be global.

In order to limit the scope of your css to this component and his child only, add a css class to the top tag of your component and put your css "inside" this tag:

template:

<div class='my-component'>
  <child-component class="first">First</child>
</div>,

Scss file:

.my-component {
  // All your css goes in there in order not to be global
}
like image 32
Tonio Avatar answered Oct 07 '22 19:10

Tonio


UPDATE 3:

::ng-deep is also deprecated which means you should not do this at all anymore. It is unclear how this affects things where you need to override styles in child components from a parent component. To me it seems odd if this gets removed completely because how would this affect things as libraries where you need to override styles in a library component?

Comment if you have any insight in this.

UPDATE 2:

Since /deep/ and all other shadow piercing selectors are now deprecated. Angular dropped ::ng-deep which should be used instead for a broader compatibility.

UPDATE:

If using Angular-CLI you need to use /deep/ instead of >>> or else it will not work.

ORIGINAL:

After going to Angular2's Github page and doing a random search for "style" I found this question: Angular 2 - innerHTML styling

Which said to use something that was added in 2.0.0-beta.10, the >>> and ::shadow selectors.

(>>>) (and the equivalent/deep/) and ::shadow were added in 2.0.0-beta.10. They are similar to the shadow DOM CSS combinators (which are deprecated) and only work with encapsulation: ViewEncapsulation.Emulated which is the default in Angular2. They probably also work with ViewEncapsulation.None but are then only ignored because they are not necessary. These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.

So simply doing:

:host >>> .child {}

In parent's stylesheet file solved the issue. Please note, as stated in the quote above, this solution is only intermediate until more advanced cross-component styling is supported.

like image 62
Chrillewoodz Avatar answered Oct 07 '22 19:10

Chrillewoodz