I am getting stuck trying to implement the PrimeNg Inputnumber element: https://www.primefaces.org/primeng/showcase/#/inputnumber
As per its documentation, there are a couple of attributes that can be used to style the input element, most notably styleClass and inputStyleClass. Unfortunately, neither of them work but rather they get completely ignored.
component.html:
<p-inputNumber
inputStyleClass="form-control-inputnumber" [(ngModel)]="subwinFld.orderAdd.doubleVal">
</p-inputNumber>
Global styles.css
.form-control-inputnumber {
background:red;
width: 100%;
}
I have used and successfully styled other primeNg elements before, using the exact same strategy, for example the p-calendar element. However, here it completely ignores the attribute.
What am I doing wrong?
Try to add :host ::ng-deep
Style are scoped, and there are not inherited by nesting.
:host ::ng-deep .form-control-inputnumber {
background:red;
width: 100%;
}
styleClass is the property that put the class on the first level of a PrimeNG Component.
inputStyleClass is the property that will put the class on the input itself for this specific component.
I often have to play with the style encapsulation with styleClass, so I believe it is the same for inputStyleClass
Word about ::ng-deep deprecation
Yes, for sure it is deprecated. To be totally fair, there is an alternative. But the alternative counterpart is huge and in my opinion, the big picture is worst.
You can make it work by changing your ViewEncapsulation in your component with :
encapsulation: ViewEncapsulation.None
as follow
#Component({
selector: '',
template: '',
styles: [''],
encapsulation: ViewEncapsulation.None // Use to disable CSS Encapsulation for this component
})
Reference 1 about alternatives and reasons of deprecation
Reference 2 about alternatives of ::ng-deep
The choice is yours, but for my part I continue to use this methodology with third party library like primeNG, because there is no real alternative.
You either choose to make your style global or your style scoped.
Kill the encapsulation for the sake of a third party library usage, seems to me an overkill process.
By making your ViewEncapsulation to none, you give up on style encapsulation, so beware of it.
HTML:
<p-inputNumber styleClass="input-styling"></p-inputNumber>
CSS:
::ng-deep .input-styling input {
width: 20px !important;
}
The cause for the missing styling was a runtime error in the typescript of the component, that prevented the correct compilation of the DOM.
I assumed that did not matter, since they should not be related at all, but they are (somehow). Since others may have the same erroneous assumption, I am leaving this question here, rather than deleting it.
Simply add
styleClass="w-full" to p-inputNumber tag to adjust 100% width or according style to reach desired width in reference to https://www.primefaces.org/primeflex/width
No encapsulation: ViewEncapsulation.None is needed and no extra css classes/styling is required.
Related
For my project I use mat-grid from Angular Material. The text/content of a mat-grid-tile is always centered in the middle of the tile. My question is: How can I align the text on the top and/or the right/left?
I didn't find an answer in the docs of Angular Material itself and couldn't find proper help otherwise. The only working solution I found, was based on ::ng-deep:
mat-grid-tile.blue ::ng-deep.mat-figure{
background: #2db7f1;
color: #FFFFFF;
display: flex;
justify-content: flex-start;
}
Sadly, the latest version of Angular Material says that ::ng-deep is deprecated:
Are there any alternative solutions?
Ways to avoid ::ng-deep
I think you bascially have two options if you want to get rid of ::ng-deep:
Place your custom css in your global styles.css
Place your custom css in your component.css but set encapsulation: ViewEncapsulation.None
Please note: Be aware that for both options your custom css will no longer be scoped, instead it will be applied globally to the entire application.
Reasons why using :host ::ng-deep could be a good idea
First of all: By adding :host in front of "::ng-deep", the styles are applied only to the styles of the elements that are deep in the corresponding component. So thanks to :host the styles will not be global.
What's more, ::ng-deep has no alternative in Angular so far. Even though it is deprecated for two years, there is no clear information when (and if) it will be removed. As a consequence it is still possible to use it. (Source)
I'm relatively new to Angular, and I have a doubt about component stylesheets.
I have an Angular 12 app and created a component named my-component. The template of the component in question is something like this:
my-component.html
<div>
...some html...
<some-other-angular-component></some-other-angular-component>
...some other html...
</div>
some-other-angular-component is another component, either from the app itself or a third party library.
Now, what I want to do in my-component is apply some CSS rules to the contents of some-other-angular-component. I know that the HTML it generates contains classes that I can target, so I tried to add this to my component CSS:
my-component.scss
.some-other-angular-component-inner-class {
background-color: red;
}
However, this doesn't work, it appears that the component's CSS file only applies rules to the HTML defined directly in the component's template, not the HTML generated by sub-components.
Is there a way to make this work? I find myself having to add my CSS to the webapp's main style.scss file, even when I want to apply the rule only to the particular some-other-angular-component instance inside of my-component. It makes styling confusing and needlessly fragmented. Is this intended, or what am I missing?
I think you may want to look into View Encapsulation.
#Component({
selector: 'app-no-encapsulation',
template: `
<h2>None</h2>
<div class="none-message">No encapsulation</div>
`,
styles: ['h2, .none-message { color: red; }'],
encapsulation: ViewEncapsulation.None,
})
export class NoEncapsulationComponent { }
These styles will be added to head and will be applicable to other components as well if style rule matches.
Please note, with this you are only enabling this behaviour for just this component. Chances of overlapping CSS rules is still there but is lot less in comparison to directly putting styles in style.css.
I will also suggest that you add .class or #id attribute in mark up to ensure that your rules don't overlap by default.
For example:
.my-component .rule-one {
}
It will ensure that my rules are only applied are on component that has this class applied on it.
I have a couple Angular components that route back and forth to one another. They both have mat-form-field's. In one component, I am overriding the styling of the underline component like so:
::ng-deep .mat-input-underline {
display: none;
}
When I click on the link to go back to the other component, the styling as defined as above carries over and the underline components are gone. I tried to add styling like:
::ng-deep .mat-input-underline {
display: revert;
//or
display: unset;
//or
display: initial;
}
But none of them work. How can I override the material design styling on just one component but not the others?
Your issue is caused by ::ng-deep, which will apply style to all .mat-input.underline elements in the page once the component has been loaded and style injected.
If you really want to keep the ::ng-deep combinator, you can add the :host selector to prefix your rule, which will target the host element and not leak the css to other components (apart from child components)
:host ::ng-deep .mat-input-underline
{
display: none;
}
https://angular.io/guide/component-styles#host
Style your component this way, this styling would not leak to the child component. Use ::ng-deep within :host but exactly like I have done below.
:host {
::ng-deep p, .py-8 {
margin: 0 !important;
}
}
I'm assuming you are using Angular Cli to generate your components...
You need to Emulate the encapsulation property on your Component. Although Angular defaults to 'Emulate'. (Thanks David, for correcting me).
In a nutshell, Emulated allows your component to make use of global styles, while keeping its local styles to itself.
#Component({
selector: 'app-child-component',
template: `<div class="parent-class">Child Component</div>`,
encapsulation: ViewEncapsulation.Emulated
})
Also, ::ng-deep is meant to pass styles from parents to children. So if you are trying to keep your child elements from adopting the styles of their parents, using that is working against you.
"/deep/" is deprecated and "::ng-deep" is the way but be careful.
Please go through below official documentation for detailed information.
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
How and where can one use ::ng-deep in Angular 4?
Actually I want to overwrite some of the CSS properties of the child components from the parent components. Moreover is it supported on IE11?
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
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;
}
USAGE
::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.
DEPRECATION
"deep" manipulations are actually deprecated too, BUT it's still 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.
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
I looked through all those answers and found nobody mentioned a child component can pass a style CSS in from its parent.
In component ts file, you can use this:
#Input() styles: any = {};
In component html file, you use this:
[ngStyle]="styles"
in parent, you use this :
<yourComponent [styles]="{backgroundColor: 'blue', 'font-size': '16px'}">
Please see more details here: Best way to pass styling to a component
In this way, we didn't break encapsulation, which is one of those most important Object orientation principles
Use ::ng-deep with caution. I used it throughout my app to set the material design toolbar color to different colors throughout my app only to find that when the app was in testing the toolbar colors step on each other. Come to find out it is because these styles becomes global, see this article Here is a working code solution that doesn't bleed into other components.
<mat-toolbar #subbar>
...
</mat-toolbar>
export class BypartSubBarComponent implements AfterViewInit {
#ViewChild('subbar', { static: false }) subbar: MatToolbar;
constructor(
private renderer: Renderer2) { }
ngAfterViewInit() {
this.renderer.setStyle(
this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
}
}
I was wondering how to override the encapsulated CSS of an external component.
So I am using material2 in my project and the tabs component has a the attribute overflow set on tab-body. Is it possible to override the overflow value?
You can use the special css /deep/ instruction. See the documentation
So, if you have
app
sub-component
target-component
<div class="target-class">...</div>
You can put in your apps css (or less):
/deep/ .target-class {
width: 20px;
background: #ff0000;
}
Obviously, you can put this css fragment in sub-component as well.
From this article
Although the style of a component is well isolated, it can still be easily overridden if necessary. For that, we just need to add an attribute to the body of the page:
<body override>
<app></app>
</body>
The name of the attribute can be anything. No value is needed and the name override makes it apparent what its being used for. To override component styles, we can then do the following:
[override] hello-world h1 {
color:red;
}
Where override is the attribute, hello-world is the target component, and h1 is whatever you are trying to restyle. (get this right or it wont work).
Your component hello-world would be
selector: 'hello-world',
styles: [`
h1 {
color: blue;
}
`],
template: ` <h1>Hello world</h1> `
I think this is the most elegant way.
Alternatively if you are building a library of some sort, you can reset the styling altogether by doing something fancy in your css like:
:host-context(.custom-styles) {
//.. css here will only apply when there is a css class custom-styles in any parent elem
}
So then to use your component you'd use
<hello-world class="custom-styles">
But this is way less convenient than the first option.
::ng-deep .tag-or-css-class-you-want-to-override {
/* Add your custom css property value. */
}
The syntax ::ng-deep is used to override outside css class or tags without using ViewEncapsulation.None.
I see variations of this question a lot and since this is the top question on the subject I want to give the simplest answer. ng-deep and similar functionality is deprecated, so it's best to just rely on vanilla CSS.
Simply create a CSS selector with a higher specificity.
Most people (including myself) get hung up trying to do that because they don't understand two things:
Angular View Encapsulation
CSS Specificity
Angular View Encapsulation
View Encapsulation ensures CSS within a component only affects that component. To affect other components, you need some global CSS. You can do this by using a global style file like styles.css or by disabling View Encapsulation on a component.
#Component({
...
encapsulation: ViewEncapsulation.None
})
CSS Specificity
When two selectors select the same element, the CSS that actually gets applied is based on specificity: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
You can increase specificity by simply adding more elements to your CSS selector. For example p.className is more specific than just .className. If you're lazy, you can just repeat a class name to increase specificity. .className.className is more specific than .className.
So to override any CSS in an Angular project, go into styles.css and repeat the class selector until your CSS has a higher specificity than the original.
.className.className.className {
color: red;
}
Didn't work? Add another .className.
Just check the class that is being applied to the tabs by the external component (use Inspector or any other tool). In your style css file, add the same name of the class for the tabs and set the overflow property along with adding !important to it to make sure it overwrites the previous one. Also make sure your css link to the page is added after the external component css link if any.
Hope this helps.
::ng-deep .css-class-you-want-to-override{
/*your custom css property value. like below */
background: white !important;
}