ng-deep is effecting sibling components - css

I ran into an issue using Angular Material Design where I need to use ng-deep in order to adjust the styling of an accordion. However, I am using an accordion elsewhere and it is grabbing the same styles. This is not desired.
Is it supposed to do that? How do I fix it?

ng-deep is deprecated, and support is being removed from major browsers. You can read more about it in the Angular Docs.
I would suggest you to remove the view encapsulation from the component instead (None removes style encapsulation for that component, so you can target Angular Material styles).
import { ViewEncapsulation } from '#angular/core';
#Component({
selector: 'app-example-component',
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss'],
encapsulation: ViewEncapsulation.None
})

I found that in order to keep the styles limited to the component, I had to encapsulate the ::ng-deep code with :host like so:
:host {
::ng-deep {
/* ... custom styles here */
}
}

Related

How to prevent Angular element (web component) from overriding the style of its parent

I have some issue with my Angular web component.
My angular application contains the web component as a child, but the issue is the css of the child component is also applying to its parent.
For instance, in web component, there's some style on its body tag. However, it is also overriding the style of its parent. Is there any way to avoid this?
<div id="my-app">
<webcomponent></webcomponent>
</div>
If you have built your webcomponent with Angular Elements, you can make use of dom / style isolation by setting ViewEncapsulation to ShadowDom:
import { Component, ViewEncapsulation } from "#angular/core";
#Component({
selector: "webcomponent",
template: `
<h3>Webcomponent</h3>
`,
styleUrls: ["./webcomponent.css"],
encapsulation: ViewEncapsulation.ShadowDom
})
export class WebcomponentComponent {}
Please notice that by using shadow dom, you will also not be able to style html inside the component from outside the component.
I've used :host ::ng-deep successfully to achieve what you're looking for.
For the CSS inside web component, add :host ::ng-deep prior to your CSS element. Ex: :host ::ng-deep .my-class { color: blue }
From the docs, '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'
Docs: https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

ViewEncapsulation changes css styles specificity(weight)

I have created a new Angular CLI project and a component where I have tried work on css specificity. Wherewer I tryed, class styles overwrite tag styles, but only on Angular project it's working vise versa
I have founded that ViewEncapsulation.None makes the css styles show darkgreen backgound-color and with the angular default view encapsulation (ViewEncapsulation.Emulated) browser shows aqua background-color.
component code
import { Component, OnInit } from '#angular/core';
import {ToastrService} from "ngx-toastr";
//import {ViewEncapsulation} from "#angular/cli/lib/config/schema";
#Component({
selector: 'app-toastr',
templateUrl: './toastr.component.html',
styleUrls: ['./toastr.component.css'],
//encapsulation: ViewEncapsulation.None
})
html code
<div>
<div class="myspan">
something
</div>
</div>
and styles
div div{
background-color: aqua;
}
.myspan {
background-color: darkgreen;
}
I expect to receive an answer why it works differently
FYI
ViewEncapsulation.Emulated: Any styles we define on a component don’t leak out to the rest of the application. But, the component still inherits global styles like twitter bootstrap.
ViewEncapsulation.Native: Styles we set on a component do not leak outside of the components scope. Component is also isolated from the global styles we’ve defined for our application.
ViewEncapsulation.None: We are not encapsulating anything, the style we defined in our component has leaked out and started affecting the other components.

Applying CSS from an Angular component to a sub-component

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?
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;
}
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.

Angular does not encapsulate css when using View encapsulation

I Have two menus in my app.
Both of them are using primeng Panel Menu
I have changed their css.
The problem is now after adding the second-menu to my app, left-menu's style has changed.
I tried to use View encapsulation on both of them, the left-menu style still not encapsulated
Here's the first menu header
#Component({
selector: 'app-left-menu',
templateUrl: './left-menu.component.html',
styleUrls: ['./left-menu.component.css'],
encapsulation: ViewEncapsulation.Emulated
})
Second menu
#Component({
selector: 'app-second-menu',
templateUrl: './second-menu.component.html',
styleUrls: ['./second-menu.component.css'],
encapsulation: ViewEncapsulation.Emulated
})
In my CSS I use ng-deep and :host
here's an example
:host ::ng-deep .ui-panelmenu-header.ui-state-default:hover {
background-color: #555555;
}
Here's a stackblitz example
I won't add all the CSS because it's the same on both styles
Using only ::ng-deep will affect all the classes in the project even if not children of the component where the css is declared. (here is a simple stackblitz reproduting this behavior)
If you want to affect only child elements of the component but not the elements on the same level, you should use :host with the ::ng-deep.
Here is a fork of your stackblitz with a fix suggestion.

Need to find CSS Selector for Material Design 2's md-dialog-container

Desperately trying to find a selector for md-dialog-container in angular 2's material design with no success.
I can make changes in f12 of chrome with no problem, but carrying out those changes with a valid selector in css is a problem. Researched /deep/ but it is now deprecated.
I have tried md-dialog-container {}, md-dialog-container.md-dialog-container{}, and md-dialog-container.md-dialog-container[role="dialog"] with no success.
Attached are images of me making these changes in f12 of chrome with no problem.
Here's what worked for me:
Set this on the dialog component itself:
encapsulation: ViewEncapsulation.None
In the parent component set the panelClass on open e.g.
this.dialogRef = this.dialog.open(myDialogComponent, {
panelClass: 'my-dialog'
});
In the css for the dialog component specifiy the panelClass e.g.
.my-dialog {
.mat-dialog-container {
padding: 0;
}
}
The issue you're running into is due to ViewEncapsulation. By default, Angular2 uses an emulated Shadow DOM which prevents styles from components affecting each other. You can opt out of ViewEncapsulation (not recommended) or you could use the /deep/ selector. According to Angular documentation in the link provided it is alright to use this selector using Angular's default emulated Shadow DOM.
From my understanding, Angular has its own CSS processor that should should make it alright for you to use these selectors for right now. I assume they're translated. If using these is truly not an option for you, you'll have to switch to ViewEncapsulation.None.
import {ViewEncapsulation} from '#angular/core'; // and any other imports
#Component({
selector: 'my-selector',
templateUrl: './my-selector.component.html',
styleUrls: ['./my-selector.component.scss'],
encapsulation: ViewEncapsulation.None
})
For Angular and Material >6.x, I was able to use the ::ng-deep selector:
::ng-deep .mat-dialog-container {
padding: 16px;
}
I have tried every option mentioned above, but somehow with Angular 2 none seemed to work. I finally got it working by adding this line to my css.
.mat-dialog-container {
padding: 0px !important;
}
What worked for me was:
In the parent component set the panelClass on open e.g.
this.dialogRef = this.dialog.open(myDialogComponent, {
panelClass: 'my-dialog'
});
In the css
.my-dialog .mat-dialog-container{
padding:0 !important;
}
The benefit of above solution is that it will only remove padding from a specific dialog not all dialogs in the application.

Resources