I am displaying a mat-select
inside a ngx-smart-dialog
, when I open the select
it shows behind the dialog. I found this and this with this solution:
.cdk-global-overlay-wrapper, .cdk-overlay-container {
z-index: 9999!important;
}
That's solves the issue if I put it in the global .scss
file. What I want to know is (because in what I read I didn't find an explanation) why putting it inside the component's view (i.e., the modal component's view) it doesn't work.
Thanks in advance!
By default, angular scopes a component's CSS / SCSS to a component using a special attribute selector that Angular automatically creates. This means that component styles only affect DOM elements in that component's view. Put another way, the component's styles only affect DOM elements which are children of the component.
mat-select
renders the overlay pane using the CDK overlay package (which I think uses a CDK portal itself). The CDK overlay package renders the mat-select's overlay pane outside of your Angular application's root component (appended to the documentbody
). This means that, despitemat-select
being inside your component's template, and despite themat-select
element being a child element of your component in the DOM, the mat-select's overlay pane is NOT a child element of your component in the DOM. This means that your component's styling will not touch the overlay pane (or any other elements which are not children of your component).I've run into this issue before myself. Personally, I consider this behavior to be a bug in Angular's emulated css scoping functionality. However, the angular team is aware of the issue and views it as an acceptable limitation of their implementation. I think I remember seeing a comment from one of the Angular maintainers that they currently don't know of a way of fixing this issue in a performant manner (so I don't think this will ever change). Similarly, native shadow DOM encapsulation ONLY allows a component's CSS to affect children of a component, so this causes the same issues when rendering overlays (I believe the spec made this decision for performance reasons as well).
This all being said, there are two ways you can place the css in your component's css file css file and still make things work (instead of needed to place the css in a "global" css file).
@Component({encapsulation: ViewEncapsulation.None})
option. This disables css scoping for the component making all of the component's css "global". Unlike normal "global" css, a component's css is added and removed from the DOM as a component is created / destroyed (so the component's css will only be in the DOM if the component is).Set a component's css scoping to
ViewEncapsulation.Emulated
(which is the default) and use the angular custom::ng-deep
pseudo selector to selectively remove scoping from certain css styles in the component's css file.Example:
::ng-deep { .cdk-global-overlay-wrapper, .cdk-overlay-container { z-index: 9999!important; } }
::ng-deep
selector is deprecated in angular, but the angular team has no current plans to remove the selector and they still recommend you use it, if needed, for the time being.ViewEncapsulation.Native
andViewEncapsulation.ShadowDom
don't support the::ng-deep
selector (and don't have any support for piercing selectors).