Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep .
But there's more. Both APIs ::ng-deep and /deep/ are deprecated and will eventually be removed in the future.
Angular's API states that the ng-deep psuedo-class is deprecated. completely disables view-encapsulation for that rule. If we use it without the :host pseudo-class, it will make the style-rule global, not a good thing. There's something odd about Angular view encapsulation which gets style specificity wrong.
There is no alternative to ::ng-deep. In Angular, like in any other framework, sometimes you have to style a child component based from a parent component. Since Angular provides encapsulation of CSS (what is great!) it is not a straight forward task (it should not be).
Usually /deep/ “shadow-piercing”
combinator can be used to force a style down to child components
. This selector had an alias >>> and now has another one called ::ng-deep.
since /deep/ combinator
has been deprecated, it is recommended to use ::ng-deep
For example:
<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>
and css
.overview {
::ng-deep {
p {
&:last-child {
margin-bottom: 0;
}
}
}
}
it will be applied to child components
::ng-deep
, >>>
and /deep/
disable view encapsulation for specific CSS rules, in other words, it gives you access to DOM elements, which are not in your component's HTML. For example, if you're using Angular Material (or any other third-party library like this), some generated elements are outside of your component's area (such as dialog) and you can't access those elements directly or using a regular CSS way. If you want to change the styles of those elements, you can use one of those three things, for example:
::ng-deep .mat-dialog {
/* styles here */
}
For now Angular team recommends making "deep" manipulations only with EMULATED view encapsulation.
"deep" manipulations are actually deprecated too, BUT it stills working for now, because Angular does pre-processing support (don't rush to refuse ::ng-deep
today, take a look at deprecation practices first).
Anyway, before following this way, I recommend you to take a look at disabling view encapsulation approach (which is not ideal too, it allows your styles to leak into other components), but in some cases, it's a better way. If you decided to disable view encapsulation, it's strongly recommended to use specific classes to avoid CSS rules intersection, and finally, avoid a mess in your stylesheets. It's really easy to disable right in the component's .ts
file:
@Component({
selector: '',
template: '',
styles: [''],
encapsulation: ViewEncapsulation.None // Use to disable CSS Encapsulation for this component
})
You can find more info about the view encapsulation in this article.
I would emphasize the importance of limiting the ::ng-deep
to only children of a component by requiring the parent to be an encapsulated css class.
For this to work it's important to use the ::ng-deep
after the parent, not before otherwise it would apply to all the classes with the same name the moment the component is loaded.
Using the :host
keyword before ::ng-deep
will handle this automatically:
:host ::ng-deep .mat-checkbox-layout
Alternatively you can achieve the same behavior by adding a component scoped CSS class before the ::ng-deep
keyword:
.my-component ::ng-deep .mat-checkbox-layout {
background-color: aqua;
}
Component template:
<h1 class="my-component">
<mat-checkbox ....></mat-checkbox>
</h1>
Resulting (Angular generated) css will then include the uniquely generated name and apply only to its own component instance:
.my-component[_ngcontent-c1] .mat-checkbox-layout {
background-color: aqua;
}
Make sure not to miss the explanation of :host-context
which is directly above ::ng-deep
in the angular guide : https://angular.io/guide/component-styles. I missed it up until now and wish I'd seen it sooner.
::ng-deep
is often necessary when you didn't write the component and don't have access to its source, but :host-context
can be a very useful option when you do.
For example I have a black <h1>
header inside a component I designed, and I want the ability to change it to white when it's displayed on a dark themed background.
If I didn't have access to the source I may have to do this in the css for the parent:
.theme-dark widget-box ::ng-deep h1 { color: white; }
But instead with :host-context
you can do this inside the component.
h1
{
color: black; // default color
:host-context(.theme-dark) &
{
color: white; // color for dark-theme
}
// OR set an attribute 'outside' with [attr.theme]="'dark'"
:host-context([theme='dark']) &
{
color: white; // color for dark-theme
}
}
This will look anywhere in the component chain for .theme-dark
and apply the css to the h1 if found. This is a good alternative to relying too much on ::ng-deep
which while often necessary is somewhat of an anti-pattern.
In this case the &
is replaced by the h1
(that's how sass/scss works) so you can define your 'normal' and themed/alternative css right next to each other which is very handy.
Be careful to get the correct number of :
. For ::ng-deep
there are two and for :host-context
only one.
Just an update:
You should use ::ng-deep
instead of /deep/
which seems to be deprecated.
Per documentation:
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.
You can find it here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With