angular icon indicating copy to clipboard operation
angular copied to clipboard

Clarify information about deprecation of :ng-deep and recommend replacement

Open cvmocanu opened this issue 5 years ago • 72 comments

The documentation at https://angular.io/guide/component-styles states this about :ng-deep:

The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep).

As I understand, Angular was using the browser support for the piercing selectors /deep/ and >>>.

But :ng-deep is surely not supported by any browser. And this is what I find confusing in the documentation. I don't understand what browser support has anything to do with :ng-deep.

The way I understand it, :ng-deep prevents Angular from appending the attribute selectors to all selector following it.

So, this CSS in a component:

:host ::ng-deep .my-button .ui-button-text {
    font-weight: bold;
}

will be transformed to:

[_nghost-c12]     .my-button .ui-button-text {
    font-weight: bold;
}

Without :ng-deep, this will be produced instead:

[_nghost-c12]     .my-button[_nghost-c12] .ui-button-text[_nghost-c12] {
    font-weight: bold;
}

(obviously breaking my intention).

I find 2 problems with the documentation, as it stands now:

  • I don't see any relationship between lack of browser support for piercing selectors and deprecating :ng-deep
  • I don't see any reason to deprecate :ng-deep (since it just tells Angular: "keep your attribute selectors away from my styles")

I propose the following:

  • if I missed anything, and there is a valid reason why :ng-deep should be deprecated, the documentation should be changed to explain why
  • if my reasoning above is correct, remove the section about deprecating :ng-deep, keeping the deprecation notice only for the piercing selectors /deep/ and >>>.

cvmocanu avatar Jul 27 '18 09:07 cvmocanu

Duplicate of https://github.com/angular/angular/issues/17867.

:ng-deep is only used to provide deprecating stage, allowing user to drop this usage with a forgiving time period. It's never a designed new feature of Angular.

:ng-deep is indeed not supported by browser, that's why it shouldn't be supported by Angular in the first place.

trotyl avatar Jul 27 '18 09:07 trotyl

:ng-deep is indeed not supported by browser, that's why it shouldn't be supported by Angular in the first place.

I fail to see the logic in this. :ng-deep doesn't need browser support. It only needs Angular pre-processing support, and we already have this.

cvmocanu avatar Jul 27 '18 09:07 cvmocanu

@cvmocanu The ViewEncapsulation.Emulated is an exact shim of Shadow DOM behavior, there won't be any so-called Angular rule for that.

trotyl avatar Jul 27 '18 10:07 trotyl

I guess I need to do some reading on the Shadow DOM.

It looks to me that the people on the Shadow DOM standards commission just deprecated a useful feature, without providing an alternative :(

cvmocanu avatar Jul 27 '18 12:07 cvmocanu

@trotyl #17867 had no resolution.

Angular seems confused by whether it wants to offer Angular features or be a compatibility layer for W3C ~specs~ drafts (which are a constantly moving target, making Angular an unstable platform).

pauldraper avatar Jul 27 '18 15:07 pauldraper

Looks like the resolution for https://github.com/angular/angular/issues/17867 (thanks for the link, @trotyl ) is to watch https://github.com/angular/angular/issues/23636. This seems to be an open question of what the Angular platform supports, and that issue contains the discussion.

I believe the documentation is, for now, correct and complete:

"The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools."

When we have more information about the replacement options, we will publish them.

jenniferfell avatar Aug 09 '18 23:08 jenniferfell

@IgorMinar When you get a chance, is my assessment above correct? Is there anything we can or should add now to the documentation here: https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

Thank you.

jenniferfell avatar Aug 09 '18 23:08 jenniferfell

Has there been any resolution to this? The documentation just leads users to search for an alternative to :ng-deep which in turn leads them to a handful of GitHub issues like this one.

Fokey avatar Feb 27 '19 15:02 Fokey

Most of my Custom Elements comprise nested Angular Components. Within a Custom Element, I want to be able to apply styles to the nested components. I understand that we don't want styles to bleed into the Custom Element from the page, but from within the Custom Element, I should be able to style the components that I'm using. Ideally, the Custom Element [Web Component] would be shielded (or sandboxed), but the ability to apply styles to nested components within the Custom Element is a really useful feature. Is it possible for the Web Component to use Shadow DOM, but inside the Shadow DOM Angular still provides an emulated environment within which ::ng-deep would work. No bleeding in or out!

gchurchley avatar Mar 01 '19 22:03 gchurchley

@Fokey the clear choice replacement (or at least partial replacement) is the standardized ::slotted().

See #27614 but if you're looking for any participation/response from the Angular team you will be disappointed :/

pauldraper avatar Mar 02 '19 04:03 pauldraper

While I cannot comment on the "best practices" aspect, I can share how we are currently using this feature. We use several third party UI components that come bundled with their own CSS. Some of these components offer limited customization options (e.g. no support for templates and no ability to set CSS classes), so our options include: 1) apply styles globally, 2) use ng-deep, 3) edit their source code, or 4) find a different library. We opted for option 2, as it enables us to style each component that we don't have easy control over. Granted, it's not "best practice" but in the industry we often have to deal with / work around others' code.

neil-119 avatar May 22 '19 05:05 neil-119

@neil-119 same here.

  1. is most often not possible
  2. not a solution
  3. little-bit old-school isnt it?
  4. elegant solution - still didnt get a reason for deprecation in browsers..

montella1507 avatar Jun 14 '19 14:06 montella1507

@neil-119 you are missing the best option...

Rather than using global styles (and having a huge src/app/styles.scss file), given you want to use such a library component in a component:

  1. define a class on the component's container element
  2. set the component to encapsulation: ViewEncapsulation.None
  3. wrap all styles in the component (SCSS) with the class of the component's container element
  4. target any selectors that you want in the library component

This allows you to style that library component differently in different parts of your app rather than having a single global style.

Note that in some, concise, isolated cases, the single global style is the best approach.

This can be used to eliminate your dependence upon ::ng-deep.

Splaktar avatar Jun 22 '19 08:06 Splaktar

@Splaktar is there any reason not to use component selector as CSS selector then?

something-list.component.ts -> "app-something-list"

// components/something-list.scss app-something-list { color: blue; }

BTW i think we have the same exact problem with neil-119 - 3rd party library code and better way to override visual than "super ultra selectors"

montella1507 avatar Jun 22 '19 08:06 montella1507

@montella1507 I'm not sure that I understand your example. I wouldn't recommend targeting the top level app's selector from a child component. I think that it's best to only style down within your component tree (not up).

Here's a real example (html)(ts) of what I mentioned above.

Splaktar avatar Jun 22 '19 08:06 Splaktar

Tired of seeing stackoverflow answers that say 'don't use ::ng-deep because it's deprecated'. That's just delusional right now. Use it.

simeyla avatar Jun 28 '19 02:06 simeyla

::ng-deep is going to hold the web record for long-lived deprecated API.

pauldraper avatar Jul 11 '19 02:07 pauldraper

Tired of seeing stackoverflow answers that say 'don't use ::ng-deep because it's deprecated'. That's just delusional right now. Use it.

I don't see why it should be deprecated in the first place. Right now it's just an angular thing, telling the angular compiler not to scope that style to the component and it's not related to browsers' implementations.

ndraiman avatar Jul 11 '19 06:07 ndraiman

https://update.angular.io says

both are deprecated but using ::ng-deep is preferred until the shadow-piercing descendant combinator is removed from browsers and tools completely.

The deep selector was decided to be remove in in April 2015 by WAWG. ::ng-deep was remove from Chrome starting v63 in Dec 2017.

Surely the Angular team will follow through on that any day now /s

pauldraper avatar Jul 11 '19 21:07 pauldraper

I am also using ::ng-deep in project. It would be nice to have an official answer if its gonna be deprecated from Angular.

gkaravitis avatar Jul 12 '19 06:07 gkaravitis

@gkaravitis it's already deprecated. It's not clear when it will be removed.

Splaktar avatar Jul 14 '19 05:07 Splaktar

@Splaktar Let's see... As of today 533 repositories use it and 44k code files in github alone. I don't think it can go anywhere anytime soon!

Educating people for the best use cases is more important - eg. when to create a truly global style sheet, or a 'theme' style file (neither of which would need it) and when to actually use it in a component (if absolutely necessary).

simeyla avatar Jul 14 '19 05:07 simeyla

@gkaravitis The things are still present the 2 next major versions after they are depreciated. After that, they are candidates for removal. So if something was depreciated in version 7 for example, it's possible to expect that it could be removed in version 10. https://angular.io/guide/releases#deprecation-practices

mlc-mlapis avatar Jul 14 '19 12:07 mlc-mlapis

@mlc-mlapis https://angular.io/guide/deprecations#index has more specific information for planned removal of deprecations.

Splaktar avatar Jul 14 '19 14:07 Splaktar

@mlc-mlapis @Splaktar So after investigate it a bit and with your valuable contibution we decided that its best even on css level to have separation of concerns. We planned to refactor our code and omit the :ng-deep.

gkaravitis avatar Jul 14 '19 19:07 gkaravitis

@gkaravitis could you share your solutions for your refactor? So far, I've been using global classes on app.component ViewEncapsulation.None but that's just messy. Any component level solution?

evanjmg avatar Aug 12 '19 18:08 evanjmg

@evanjmg thought I'd chime in fwiw. After eading this thread I replaced /deep/ with ::ng-deep. My belief is that ng-deep is going to exist (within Angular) for quite awhile.

BenRacicot avatar Aug 12 '19 19:08 BenRacicot

@BenRacicot ::ng-deep is not the recommended solution and it will be removed eventually. This issue is about finding an alternative. I noticed that they say Until then ::ng-deep should be preferred for a broader compatibility with the tools. - but that's not a solution as it's going to be deprecated nonetheless.

evanjmg avatar Aug 12 '19 19:08 evanjmg

The most practical step right now would be to add a section in the docs explaining each common use case for ::ng-deep and what are the pros / cons of any alternatives for each.

This issue will be impossible to reconcile if we don't have a list like this. And worse, people get scared by the word 'deprecated' and jump hastily to the first solution they find on StackOverflow.

If everything is outlined in a detailed tutorial it'll help steer people away from the worst footguns - and make it easier to migrate in future to whatever comes next.

eg.

  • Never ever ever use ::ng-deep .something at the top level of your styles. They leak globally, only after you've first viewed that component. This 100% should never be done. You are creating a global style, applied lazily.
  • Instead use :host ::ng-deep .mdc-button so that override is scoped to your component.
  • To tweak material styles globally => use global stylesheet, or theme mixins
  • To tweak material styles on an opt-in basis => use global stylesheet with a custom class applied to the component (eg. mat-form-field.compact). This works great if the tweak you made eventually becomes a feature.
  • To tweak material styles inside a specific component => use :host ::ng-deep .third-party-component
  • To set styles for the first child of a router-outlet => :host ::ng-deep router-outlet is probably ok.
  • To set styles for something that was dynamically added and therefore doesn't have ng attributes (eg. a youtube iframe) => :host ::ng-deep iframe is fine
  • Setting styles for a child component in 100 places over your app => probably bad idea!
  • Using ViewEncapsulation.None is almost never the right solution to this.

The day ::ng-deep is deprecated - if anytime soon - is the day I stop updating Angular!

Also I agree with @BenRacicot that it is going to exist for quite some time - years minimum. Angular is mature enough now and way too many projects rely on this (whether good or bad) and have too much momentum to be re-architected overnight.

simeyla avatar Aug 12 '19 19:08 simeyla

Let's recap...

  • Is there an alternative shadow piercing descendant selector (SPS)? Doesn't seem to be. So as described, we're stuck with what remains (ng-deep).
  • We could use globally scoped styles (from a global stylesheet)
  • We can set a component's style encapsulation to allow its styles to affect children
  • CSS Custom Properties can "cross" shadow boundaries but by no means replace SPSs

Are there other options I'm missing?

BenRacicot avatar Aug 12 '19 19:08 BenRacicot

ViewEncapsulation.Native and Shadow Dom is the only correct solution but it lacks pollyfills at the moment correct? https://github.com/angular/angular/issues/23636

evanjmg avatar Aug 12 '19 19:08 evanjmg

@evanjmg Given that these 'deep' things get deprecated in the first place because they break encapsulation - it very much concerns me that if everything was suddenly Native it just wouldn't work for the way people currently use third party components.

The Angular material team is quite stubborn (not trying to offend) with their adherence to the spec that they release components that just don't work for certain designs (try positioning half a dozen text fields vertically with their default spacing) - and therefore necessitate 'tweaks' usually with ::ng-deep. The alternative is for component makers to add dozens more configuration properties which doesn't seem their style at all.

If material suddenly started using Native with a polyfill then wouldn't that mean ::ng-deep or even global stylesheet would be impossible (I'm not sure but isn't that the whole point of shadow dom?).

The first stackoverflow question I referenced above doesn't even mention angular - so I'm just realizing now there's a whole parallel conversation going on in the 'web-component' world to seek inspiration from :-)

simeyla avatar Aug 12 '19 20:08 simeyla

@simeyla we see eye to eye on this directly. I pulled material from my project after a ~month.

There does seem to be several tricks as alternatives to piercing selectors but some make me cringe a little:

I'm still going to keep using ::ng-deep until it's unusable.

BenRacicot avatar Aug 12 '19 21:08 BenRacicot

There is also the ::slotted pseudo-element, which was implemented for ViewEncapsulation.Native (#11595). For ViewEncapsulation.Emulated the pull request (#31547) is currently waiting for review.

kyubisation avatar Aug 12 '19 21:08 kyubisation

Re: @simeyla

eg.

  • To tweak material styles globally => use global stylesheet, or theme mixins

For many styles this can be accomplished using the built in theming or typography features of Angular Material. For those where this doesn't apply, my suggestion here is recommended.

  • To tweak material styles one time for a very specific component => ::ng-deep would be ok here IMHO
  • To set style (eg. flex) for the first child of a router-outlet => ::ng-deep router-outlet is probably ok.
  • To set styles for something that was dynamically added and therefore doesn't have ng attributes (eg. youtube iframe) => ::ng-deep iframe is probably ok

My suggestion here is recommended over these uses of ::ng-deep.

  • Setting styles for a child component in 100 places over your app => probably bad idea!

If this is what you are facing and these styles are the same in every place, then a global style may be the correct approach. If that isn't viable, then you could wrap the external third party component in a first party component that just applies these styles (via my suggestion here).

The day ::ng-deep is deprecated - if anytime soon - is the day I stop updating Angular.

As mentioned above, there are clear, functional alternatives to ::ng-deep. You should not be depending upon it heavily in your apps.

Splaktar avatar Aug 13 '19 22:08 Splaktar

I mean, someone did submit a ::slotted() pull request.. https://github.com/angular/angular/pull/31547

Just needs to be approved by someone that can. :)

cyraid avatar Sep 22 '19 23:09 cyraid

Is /deep/ removed in Angular v.9? I can't build old library with this css selector in latest RC.3 or RC.4. Thanks!

kolkov avatar Nov 30 '19 12:11 kolkov

Is /deep/ removed in Angular v.9? I can't build old library with this css selector in latest RC.3 or RC.4. Thanks!

They were planning to remove it: https://github.com/angular/angular/issues/17867

KhaledSamir avatar Dec 11 '19 17:12 KhaledSamir

@kolkov I don't think so. Can you provide more details in a StackOverflow post or somewhere else? I.e. the error message, etc.

Splaktar avatar Dec 11 '19 18:12 Splaktar

I believe the solution here is ::slotted() for when a component wants to style elements projected into it. And ::part() for when a component consumer wants to style parts of a component. I'd assume this is what the Angular team would implement as a replacement for ::ng-deep.

Of course this requires both sides to work together to expose the API, but that is what you'd have to do in any other situation all across software development. If you own the component, implement the API. If you don't, submit a request to the developer or fork the project. This situation is no different. We should maintain that encapsulation.

Like in other languages, there's often ways to hack into it and force it to work (e.g. reflection). In Angular, you can either 1) put your styles globally (for emulated) or 2) run some JavaScript inside the shadow DOM (for native).

chris13524 avatar Dec 13 '19 01:12 chris13524

@Splaktar not sure your solution is quite good. Container component usually has not only child third-party component we wish to restyle. So view encapsulation with none value will disable styles encapsulation for everything else inside component. And if on current page there is something with the same selector - it will break styles. Furthermore Angular doesn't remove style tag from head for destroyed component. So if you have routing in your app, which I pretty sure most do, on other pages these non-encapsulated styles will crap something in case selector matched, which is likely to happen in quite a big app

gudzdanil avatar Feb 14 '20 09:02 gudzdanil

@gudzdanil if you turn off view encapsulation, you would also scope your component's styles like this:

my-component {
  // all of your styles
}

This works fine for leaf components, but not ones that project content.

chris13524 avatar Feb 14 '20 13:02 chris13524

I understand the need to deprecate ::ng-deep, that would be because it leaves the application open for unwanted CSS spread through your whole application (...) however the combination of :host and ::ng-deep is perfect, why don't you (angular team) create your own :host-deep pseudo-class selector?

Most developers complaining here doesn't need the ::ng-deep feature, they need the :host ::ng-deep combination, by now i think this is the best answer here on this thread.

luiscla27 avatar Feb 26 '20 17:02 luiscla27

so for now, ng-deep still mark deprecate, what a solution for ng-deep without using encapsulation. I want to custom some angular material component only inside my child component

nminhduc avatar Apr 15 '20 07:04 nminhduc

I understand the need to deprecate ::ng-deep, that would be because it leaves the application open for unwanted CSS spread through your whole application (...) however the combination of :host and ::ng-deep is perfect, why don't you (angular team) create your own :host-deep pseudo-class selector?

Most developers complaining here doesn't need the ::ng-deep feature, they need the :host ::ng-deep combination, by now i think this is the best answer here on this thread.

Exactly. I don't think I've come across a point where I need to style something outside of the host context. It's always been child components.

cyraid avatar Apr 15 '20 10:04 cyraid

I understand the need to deprecate ::ng-deep, that would be because it leaves the application open for unwanted CSS spread through your whole application (...) however the combination of :host and ::ng-deep is perfect, why don't you (angular team) create your own :host-deep pseudo-class selector?

Most developers complaining here doesn't need the ::ng-deep feature, they need the :host ::ng-deep combination, by now i think this is the best answer here on this thread.

So is there a current replacement for :host ::ng-deep?

claudekennilol avatar Jun 15 '20 13:06 claudekennilol

No. A possible solution is #31547 (emulation of ::slotted selector), which is waiting to be merged (or reviewed again).

kyubisation avatar Jun 15 '20 14:06 kyubisation

So is there a current replacement for :host ::ng-deep?

Just ignore the deprecated warning

luiscla27 avatar Jun 15 '20 14:06 luiscla27

Angular team, please ask the Polymer team how to get this done. Apis for custom CSS properties on a component are a few years overdue here.

dman777 avatar Jul 17 '20 20:07 dman777

Most of the times, using ::ng-deep without a preceding selector or the :host pseudo-class is wrong, as most of the times you shouldn't style things from your component which are out of its scope. That's clear.

However, what should you do if you need to style elements which are dynamically added to the page outside of your component? A good example is a tooltip, modal or popover that you're controlling from your component but it is appended by whichever library directly under the body.

You could surely define a global style in the app's css, but what if you prefer using different looking tooltips across components?

We solve this issue by giving the tooltip a custom class with the component's name (most of the libraries like ng-bootstrap etc. offer such option), then in the component's css you can write ::ng-deep .tooltip.someComponent { ... }. This way there are no conflicts, even if there's multiple components on the page at the same time, they can display tooltips from the same library with different styles.

After the functionality of ::ng-deep will have been removed from Angular, I have no idea how we could achieve this.

swirlsky avatar Sep 04 '20 06:09 swirlsky

@swirlsky I suppose you need to do positioning in global css for tooltip because it's a common behavior, and in components you need to define a template, use ViewChild to query template and then instantiate tooltip with this template. Then angular compiles template with scoped css attributes and you can define styles as usual without ng-deep

gudzdanil avatar Sep 04 '20 07:09 gudzdanil

After the functionality of ::ng-deep will have been removed from Angular, I have no idea how we could achieve this.

You would just use a global style that is wrapped by the class name of the tooltip type that you are styling. I.e.

.mat-tooltip.someComponent { ... }

Is your concern that you want to have hundreds or thousands of different components that have differently styled tooltips? And they would all be completely custom, so that the below doesn't apply?

what if you prefer using different looking tooltips across components?

Then you would use a class name (which I would always recommend) instead of the component name (not recommended). I.e.

.mat-tooltip.info { ... }
.mat-tooltip.alert { ... }

As you noted, with Material, this would be set via matTooltipClass="info" and Bootstrap and other libraries have a similar feature.

You shouldn't feel like global styles are banned or not to be used. Of course, you should avoid over using them and make smart decisions about how you name and organize them. For large teams, there should be clearly documented guidelines for global styles.

Splaktar avatar Sep 04 '20 07:09 Splaktar

@swirlsky I wrote about the proper CSS strategy to avoid this issue and many others. Angular CSS Strategies (with Stackblitz examples). It's very simple, style general styles within a global stylesheet. Then resetting styles inside a component is not an issue at all.

Note: This is also how CSS should be architected in general. If your team is relying on component scoped styles FIRST then your problems have only just begun anyways.

BenRacicot avatar Sep 04 '20 12:09 BenRacicot

@neil-119 you are missing the best option...

Rather than using global styles (and having a huge src/app/styles.scss file), given you want to use such a library component in a component:

  1. define a class on the component's container element
  2. set the component to encapsulation: ViewEncapsulation.None
  3. wrap all styles in the component (SCSS) with the class of the component's container element
  4. target any selectors that you want in the library component

This allows you to style that library component differently in different parts of your app rather than having a single global style.

Note that in some, concise, isolated cases, the single global style is the best approach.

This can be used to eliminate your dependence upon ::ng-deep.

@Splaktar nice!

I made alternatives to step2.

constructor(el: ElementRef) {
    const { nativeElement } = el;
    nativeElement.className = nativeElement.tagName.toLowerCase();
  }

OR

@HostBinding('class.app-header') addHostClass = true;

This way I don't have to add an extra container and could still access it as "host/selector" in the scss definition.

The hostbinding approach is a little hardcoded. The constructor approach is more dynamic and extensible -- you will always get your component selector as class name.

Made myself a gist, for future reference.

azamanaza avatar Nov 19 '20 18:11 azamanaza

Why then just dont use komponent selector as CSS selector then? app-comp1 {}

montella1507 avatar Nov 19 '20 18:11 montella1507

I think if we can implement ::part (https://github.com/angular/angular/issues/22515) then we could document that as an alternative to ng-deep and that might also give us the confidence to finally remove the ng-deep and associated features.

petebacondarwin avatar Jan 23 '21 20:01 petebacondarwin

@BenRacicot - I like your strategy, although it only works for "emulated" component encapsulation. If you used ShadowDOM encapsulation, then these global styles do not reach into the template. That being said, neither do the ::ng-deep styles so there is no loss there.

petebacondarwin avatar May 23 '21 11:05 petebacondarwin

Hey @petebacondarwin! Yes all true, you've inspired me to update the article and create a Stackblitz to prove out the solution to ShadowDOM encapsulation.

Maybe you've had a chance to see my article and the other Stackblitz templates? (any input would be great!) Within global styles there should also be a CSS custom properties strategy that can be used within the shadow.

Stackblitz example

Updated the Angular CSS article.

BenRacicot avatar May 23 '21 23:05 BenRacicot

Interesting idea @BenRacicot to use CSS custom properties. I had not even heard of those before.

petebacondarwin avatar May 24 '21 14:05 petebacondarwin

The [New] State of CSS in Angular has a section about Future of overriding styles:

CSS Variables open the door to well-supported APIs for component customization, allowing developers to shift away from CSS overrides and ::ng-deep.

We recommend introducing custom variables in your libraries and dependencies in order to create an API surface for customizing libraries without the need for ::ng-deep. Implementation of custom variables allows developers to have more control over their styling and provide a path away from CSS overrides and ::ng-deep.

kapsiR avatar Nov 25 '21 13:11 kapsiR

::part looks like a good native solution but I wonder what about material or other 3 rd party components where current projects use :ng-deep. The only problem imo is auto migration of :ng-deep to :part.

vugar005 avatar Dec 27 '21 21:12 vugar005

End up in this thread after looking up this issue and ::part is certainly not an option because this requires templates to have matching attributes. Cannot expect all third party libraries and content to add a custom part attribute to every single element because you would not know what someone may want to style there.

Angular could automatically wrap component styles with the component selector and move to global scope. So any inline or styleUrls styles are always wrapped by the compiler. This way nothing leaks, no globally written styles or dom piercing hacks are required.

Ketec avatar Mar 04 '22 12:03 Ketec

@neil-119 you are missing the best option...

Rather than using global styles (and having a huge src/app/styles.scss file), given you want to use such a library component in a component:

  1. define a class on the component's container element
  2. set the component to encapsulation: ViewEncapsulation.None
  3. wrap all styles in the component (SCSS) with the class of the component's container element
  4. target any selectors that you want in the library component

This allows you to style that library component differently in different parts of your app rather than having a single global style.

Note that in some, concise, isolated cases, the single global style is the best approach.

This can be used to eliminate your dependence upon ::ng-deep.

I am sorry but why is this or any other of the alternative solutions not mentioned in the angular docs, right where ng-deep is? Am I missing something? Usually when something gets deprecated, the documentation gives you the alternative 😅

nCr78 avatar Mar 19 '22 11:03 nCr78

I've been working for the past 8 months for a project that required Angular Material as its main components library. The problem is, at least 30% of the components need a certain level of customization to match de design, thus I need a way to override the nested styles of each one of these components. Of course the first thing that came up to my mind was using ::ng-deep, easy, quick and does the job. Now that ng-deep is deprecated, not supported in any way, browsers break the styles when you use them, and there is no information about clean alternatives in the Docs AFAIK, has anyone gone through something similar? any alternatives you could find? Everything helps.

martinbigsur avatar Mar 31 '22 21:03 martinbigsur

I'm finding that the most common workaround to this is to somehow use ViewEncapsulation.None in a wrapper component and put all the ::ng-deep styles in there. We could not make a bit easier by doing something like this.

@Component({
  selector: 'app-some',
  templateUrl: './some.component.html',
  styleUrls: [
    // The suggestion
    { path: './some.component.deep.css', encapsulation: ViewEncapsulation.None },
    'some.component.css'
  ]
})
export class SomeComponent implements OnInit {
  // ...
}

olafur-palsson avatar Jul 22 '22 10:07 olafur-palsson