2

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?

3 Answers 3

5

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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

tell me for more help
Thank you - I took the time to read this page: blog.angular-university.io/angular-host-context Which made me understand what was happening above: The :host targets the instance of this component, and the ::ng-deep removes the attempt to target this components direct content (and it's this part that allows you to target the sub-component) What it worrying is it's vaguely marked as 'depricated' but the idea being implemented seems sound. Time will tell!
1

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.

5 Comments

Thanks Daniel, I think your answer may appear to do the job, but I specifically was looking for if a component should be allowed to style any sub-components, and how it may do so. I think your answer doesn't address this broader conceptual question - but it's still useful for me to go look at these options to understand the wider scenario better.
The if it should be able to style a child component is primarily opinion based, and the how I answered. You specifically asked "How is this failing?" which is what I answered. I'm glad you found my answer helpful though, but be more precise in case you want more suitable answers! :)
you are the life savior bro up voted it solved my problem stuck in this from last 7 days
Glad the answer was useful, @DeepakGoyal!
but hot to stop css leak as we move to some other link than its use the previous page css is it possible like from url1 i use skin2 by encapsulation but my default skin is skin1.css but when i move to url 2 it still use skin2 not using skin1.css as its my default skin
0

check the css file that is produced at the end.

it looks like the first is physically before the second hence it's green

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.