We have an in-house Angular component library (one project), each component has basic styling.

We use this library in our App (another project).

A component in the App contains a component from our library.

From the global styles.scss in the App, I can target the elements in the library component just fine.

If I move that global CSS into the App component CSS file, try what may, I cannot target any elements inside the library component.

app-component.html

<div class="outter">
  <library-component specificityattr></library-component>
</div>

library-component.html

<div class="generic-styles">
  <p class="hello">Hello</p>
</div>

app-component.scss

library-component[specificityattr] p.hello {
    background: red;
}

styles.scss

library-component[specificityattr] p.hello {
    background: green;
}

Without the selector in styles.scss, I expect the P tag to have a red background. Only when I put the same selector in styles.scss do I get a green background.

How is this failing?

What is the correct way to style a components sub-components?

2 Answers

0
לבני מלכה On Best Solutions

Your :host component is th library-component and you want to apply css to some "deep" DOMS so it means :ng-deep

Here is working example

Use

:host library-component[specificityattr] ::ng-deep p.hello {
    background: green;
}
0
Daniel B On

What you are experiencing is an effect of the default ViewEncapsulation of components in Angular.

When you define a component such as below, the view encapsulation of the component will be the default value, which I've included inside a comment. This means that Angular won't create a so called 'shadow DOM' for your component, and all the styles will only be applied to your component.

Encapsulated component

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

If you instead want to apply the styles not only to your component, you can specify a specific ViewEncapsulation in your component declaration. Using ViewEncapsulation.None will move the styles to the DOM head, and it will still not create a shadow DOM.

Without encapsulation

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

Have a look at this StackBlitz example

It's important to keep in mind that ViewEncapsulation.None will "leak" your styles to other components, which in turn will make it harder to style your application unless you know exactly where your styles are defined.