30

I have a parent component inside which I have a child component. The parent component have some css classes, where child component extends them. I tried to use :host as looking at documentation, but cant't seem to get it work properly.

child component:

<div class="table-row body">
<div class="table-cell body-content-outer-wrapper">
    <div class="body-content-inner-wrapper">
        <div class="body-content">
            <div>This is the scrollable content whose height is unknown</div>
            <div>This is the scrollable content whose height is unknown</div>
            <div>This is the scrollable content whose height is unknown</div>
        </div>
    </div>
</div>

parent component:

         <div class="table container">
                 <div class="table-row header">
                        <button type="button" class="btn btn-info" data-toggle="collapse" data-target="#demo">Simple collapsible</button>
                        <div id="demo" class="collapse">
                            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
                            Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
                        </div>
                  </div>
            <app-child-component></app-child-component>
                </div>

parent component css:

  :host  .table {
    display: table;
  }

  :host .table-row {
    display: table-row;
  }

  :host .table-cell {
    display: table-cell;
  }

  :host .container {
   width: 400px;
   height: 100vh;
  }

  :host  .header {
    background: cyan;
 }

   :host .body {
    background: yellow;
    height: 100%;
 }

  :host .body-content-outer-wrapper {
    height: 100%;
 }

 .body-content-inner-wrapper {
    height: 100%;
   position: relative;
   overflow: auto;
}

 .body-content {
    position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
}

The problem if even I put css classes inside the child component, the layout breaks just because there is a child-component template. So the main question is what is proper way for child to inherit extend css from parent component?

Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
AlexFF1
  • 1,233
  • 4
  • 22
  • 43

4 Answers4

78

Why make things complex?

Ideal way to do would be to add refrence of parent css file in child component as well.

 @Component({
    selector: 'child-app',
    templateUrl: `./child.component.html`,
    styleUrls:['./parent/parent.component.css', './child.component.css']
})
export class ChildComponent { }
Dheeraj Kumar
  • 3,917
  • 8
  • 43
  • 80
  • my mistake, thanks anyway, just found that there is no parent child architecture, but 2 siblings components. What would be the best way in this scenario? Should I move classes to global css? – AlexFF1 Mar 27 '18 at 15:03
  • If both siblings have any parent, you can do as suggested in my answer else You can have a shared css file and add reference of shared css under "StyleUrls" in both component. – Dheeraj Kumar Mar 27 '18 at 15:04
  • if I do this, then each component is different scope, and styles are not inherited. – AlexFF1 Mar 27 '18 at 15:08
  • Are you working in AngularJS, For Angular2+. there is no limit of scope you can have shared components, shared css among multiple component just by adding reference to StyleUrls. – Dheeraj Kumar Mar 27 '18 at 15:11
  • Angular 2+, the problem is that css breaks, because of something like >>
    . The class table row is there but it breaks the app. Only when I move class to the actual selector it works. But I don't need it like that.
    – AlexFF1 Mar 27 '18 at 15:19
  • Are you saying you are trying to add classes to tag inside parent? If yes you should directly apply case in child component itself. – Dheeraj Kumar Mar 27 '18 at 15:34
  • Very much discussed here: https://stackoverflow.com/questions/36527605/style-child-components-from-parent-components-css-file, looks like there is a way with ::ng-deep but that will soon be deprecated, so there is no option that exists. Your solution will fail when there are mulitple parents that want to override css of same child. – Manohar Reddy Poreddy Dec 14 '18 at 10:47
  • If you read answer again, it is about a child using css of parent not the other way round, and it should work with multiple parents as well. – Dheeraj Kumar Dec 14 '18 at 12:59
  • That breaks the Open-Close principle. We should not modify the child component for every parent. – mdarefull Mar 12 '19 at 20:14
  • @mdarefull How does it even closely apply to open-close principle? We are not adding new feature here to child. – Dheeraj Kumar Mar 14 '19 at 13:43
  • @mdareful Aren't we? Assume the child will be used by another parent, then we should go to the child component and modify it, to reference the new style sheet, possibly breaking its previous usage. – mdarefull Mar 16 '19 at 10:30
  • If we start changing child components as per different parents' needs, doesn't it violate SRP ! I won't create such component which needs to be changed in order to be used. Again, if we are talking about making reusable components/angular elements, in that case there shouldn't be any inheritance from parent at all. – Dheeraj Kumar Mar 17 '19 at 13:53
  • This is very good, but I have a conditional on my class. Specifically with `[ngClass]` I hope that using component input it inherited too! – Jeremy Taylor Feb 27 '20 at 11:35
  • This works, but the only problem with it is that you end up creating duplicate copies of the stylesheet for each component. If this pattern is used extensively, it will bloat the size of the stylesheet considerably. – Jeff Fohl Jun 29 '20 at 23:46
  • Why create duplicate copies, you can use same copy everywhere. – Dheeraj Kumar Jun 30 '20 at 00:21
  • You’ll also have a problem if you use Sass: it won’t compile your variables if you add the style sheet in your component. You’ll have to add (at)import '../parent/parent.component.scss' in your child style sheet. It also works for 2 siblings: you can create a global style sheet next to styles.scss and (at)import it in the siblings style sheets (with a '../../other-style.scss' path). – Julien Busset Jul 15 '20 at 10:32
9

With ::ng-deep, styles will be applied to the current component, but also trickle down to the components that are children to the current component in the component tree.

Example:

:host ::ng-deep app-child-component {
       color:yellow;
     }

A good resource - Styles Between Components in Angular 2+

Damien
  • 1,582
  • 1
  • 13
  • 24
6

Another alternative to ::ng-deep and referencing the parent's css file, is to use the encapsulation component propertie :

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

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  encapsulation: ViewEncapsulation.None
})

the parent css with flow to all it's childs.

Chtioui Malek
  • 11,197
  • 1
  • 72
  • 69
  • 12
    but it will also flow to the rest of the application. Much like putting login.component.css in the global styles. Also, it makes these components susceptible to break other components. – mdarefull Mar 12 '19 at 20:15
  • 1
    @SoEzPz that's not true, I just tested and I can clearly apply a class declares in the scss of a child component in any parent. ViewEncapsulation.None makes these styles global. – michelepatrassi Jan 15 '21 at 10:59
1

why you're trying to make it complex, you can just import your parent component CSS into your cild component CSS