1

A lot of our site is structured as such:

  • component
    • component CSS
    • component template
      • child component

We often need to style the child component differently based on which parent component it was in. This is annoying, of course, but was manageable when we were using global CSS as we could simply target the specific instance with unique ID and class CSS selectors.

We're trying to now stop using global styles and encapsulating our CSS within each component. The problem with this is that, from what I see, encapsulate angular CSS will scope your CSS so that it only applies to that component...which means it also will not apply to any child components.

One solution appears to be to use ::ng-deep selectors in our component CSS to target the child. This is meeting some resistance, though, as I'm being told this also breaks encapsulation in general and could affect other parts of the site in different components.

This is where I'm confused. Some questions:

Does any style targeted with ::ng-deep become descoped so that it is global application-wide? Or is it simply 'global' within that one parent component?

If it's the former, would it be an OK practice to still use ::ng-deep, but also make sure you are using additional unique css selectors so it only applies to the child component you are targeting?

Or is there a more proper way to add styles to a particular child component instance?

DA.
  • 39,848
  • 49
  • 150
  • 213
  • 1
    `::ng-deep` is valid in the direction from parent to the deepest child so no other side effects. But I would advise being careful when targeting the deep children. Also consider [this](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep) – Eldar Jan 08 '21 at 20:19
  • @Eldar not sure that's correct, from your link it says styles within ::ng-deep are global and can bleed into other styles _if used without :host_ – BlackICE Jan 08 '21 at 20:38

2 Answers2

3

:ng-deep is global. No matter where you put it, it applies to all components. Not just children.

If you use :host :ng-deep, then it will work from that component down (Into the children, grand children etc).

The main issue working with ng-deep is that styles in Angular are lazy loaded. So in some cases, you can be viewing the site perfectly fine, then you view a particular page that uses ng-deep, then you can go back to previous pages that were fine that are now broken because the ng-deep style is applied site wide. e.x. https://tutorialsforangular.com/2020/04/13/the-dangers-of-ng-deep-bleeding/

Generally speaking, if I need to style a child component slightly differently depending on where it's placed, then I create an input variable for the child, make the parent set it, then make it a class somewhere in the child component HTML. The child component can then style that class how it see's fit and you haven't had to break encapsulation.

MindingData
  • 11,924
  • 6
  • 49
  • 68
  • Thanks for that very nice explanation. That helps a lot. Seems that this is maybe just something that wasn't fully thought through in Angular-land. I do get that global CSS is a really pragmatic solution in a lot of cases, so maybe that's really the better approach (just not usable in our situation). – DA. Jan 15 '21 at 19:50
1

::ng-deep by itself does make the style global, but when combined with :host may do what you need, but as @eldar alluded to with this link, ::ng-deep is deprecated (and has been for some time).

BlackICE
  • 8,816
  • 3
  • 53
  • 91
  • This is good info. But I guess a follow up with be...with ::ng-deep what is the recommended alternative practice going forward for handling this scenario? – DA. Jan 08 '21 at 22:26
  • haven't found one, it's been "deprecated" for over years and several versions, but unlikely to go anywhere: https://stackoverflow.com/questions/47024236/what-to-use-in-place-of-ng-deep – BlackICE Jan 12 '21 at 14:28