Styling react-select component with CSS className in Reactjs - css

I'm using react-select and I'm trying to style the Select component like written in the DOCS but adding a class with className does not work. The class tag is added to the DOM element's classes but doesn't affect the element itself. The theme stay the same.
If I add a class like this:
<Select
className='my-class'
{...selectProps}
/>
The DOM element looks like this:
<div class="my-class css-2b097c-container">
...
</div>
Which means that the default class css-2b097c-container of react-select will always "override" my custom class.
I've tried to use the classNamePrefix option but did not work either :(
In order to keep my UI design complete I need to design it with classes and not with inline styling!

classNamePrefix works for most but not all components which is kinda annoying to me. Another solution is to add your own className as stated in your question but refer to both of them in your css using [attribute*=value] selector to increase specificity.
<Select
className="mySelect"
options={options}
/>
.mySelect[class*="-container"] {
background-color: lemonchiffon;
padding: 10px;
}
Live Example

Related

How to remove the particular scss if the component get destroyed?

I am using PrimeNG for my project I used p-dropdown with appendTo body only for particular components files, and I changed the css in only one file as follow, for example
geneFinder.component.scss
.ui-dropdown-panel {
z-index: 999 !important;
}
and component file is
<p-dropdown [options]="geneoptions" formControlName="gene" appendTo="body"></p-dropdown>
But this css is affecting in all other files also. If I removed the !important it is not affecting in other pages and this is not working with particular component itself. How to fix this issue.?
you can try this
<p-dropdown [options]="geneoptions" formControlName="gene" appendTo="body" [style]={'z-index':'999 !important'}></p-dropdown>
You can also customize the z-index with the p-dropdown attribute baseZIndex. This way, you don't need to set it in css, and it affects only the dropdown where the attribute is set.
Angular is a single page application framework hence all the CSS would be combined and CSS styles will be created inside style tag of the single html page. If we are having a CSS class with name that is common to other component's elements it does affects it.
In case of component specific CSS, create a custom class name something like,
.mycomponent-ui-dropdown-panel {
z-index: 999 !important;
}
and add the class to the element of the component's html where we need this change to be applied. This will make sure that other elements of other components are not affected by the CSS style.
I fixed the issue by adding the panelStyleClass in my component,
<p-dropdown [options]="geneoptions" formControlName="gene" appendTo="body" panelStyleClass="overlay-zindex"></p-dropdown>
.overlay-zindex{
z-index: 999 !important;
}

How should a parent style a child component for Angular? I'd like a good solution that won't be deprecated

When I need a component to change slightly for a new use, I've looked at transclusion and multi-slot transclusion vs adding HTML around the component but there are still situations where a component's internal styling needs to be changed.
You can pass a style in as an input, and then set it in the template with [ngStyle].
So for a simple example i'll show how to do this with a background color.
customComponent.html
<div [ngStyle]="{'background-color': data?.backgroundColor }">
<p> the background color will be set from an input </p>
</div>
customComponent.ts
#Input('data')
data: {
backgroundColor: string;
};
parent.html
<customComponent [data]="{backgroundColor: 'grey'}"></customComponent>
Components should be self contained and programmed so they don't require refactoring whenever a new use is needed.
One solution is to add a class to the parent using ng-class, and then use regular css rules to style the child: one set of rules that requires the class to be on the parent div, and another set that doesn’t require the class to be on the parent div.
Example css:
.my_class {Normal styling}
.my_parent_div_class .my_class {Special styling goes here}

Rendering only component template in router-outlet in Angular 5

I'm having troubles using Angular router-oulet because it adds new elements to the DOM and it affects the CSS rules that are applied because it breaks the parent-child relationship of some elements. Here's an example of what I mean:
As you can see, after each <router-outlet></router-outlet> is the inserted component selector (app-fwc-dashboard-main and app-fwc-policy-main in the code) and all the component template markup comes underneath it. This makes that there are some CSS rules that are not applied and the layout is broken.
I've been comparing the code from one version to the other and I've realized that the component selector has the class ng-star-inserted so I've tried to add the missing CSS rules, like this:
.grid-y > .ng-star-inserted > .auto, .grid-y > .ng-star-inserted > .shrink {
height: auto;
}
.grid-y > .ng-star-inserted > .cell {
width: auto;
}
(etc)
But, for some reason I can't find, it didn't work. So my question is: Is there any way to tell Angular router outlet to inject ONLY the component template markup and avoid adding the selector?
Or is there any other suggestion for this problem? Thanks in advance!
I don't think this is possible.
As I see it you have two possible solutions:
Remove the > selectors in your css.
Include the component selector in your css.
If these doesn't work for you I suggest rewriting the code in a manner which makes it easier to work with.
You can use attribute selector for Component.
Add classes using #HostBinding and css selector :host inside styles.
#Component({
selector: '[attributeSelector]',
template: 'red text',
styles: [':host {color: red}'],
})
class A {
#HostBinding('class') class = 'boundClass';
}
In this case router-outlet will create something like
<router-outlet></router-outlet>
<div attributeSelector class="boundClass" nghost_1>red text</div>
Ilia Volk's answer showed me the right track to find the solution. I changed the component selector to this:
selector: '[app-vpn-component].grid-y.medium-grid-frame',
This way, the rendered markup is:
<div app-fwc-vpn-main="" class="grid-y medium-grid-frame ng-star-inserted">
...
</div>
And now the layout looks as before.

Overriding the encapsulated CSS of external component

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

how to add background color to input text if it is a dojo datepicker?

I can't set the background color (or border color) of an input text, if it is a dojo datepicker.
My dojo datepicker is an input text with the two additional attribute:
dojoType="dropdowndatepicker"
displayFormat="yyyy-MM-dd"
I assume dojo has its own style, so even if I provide a style that specifies the background color, dojo overrides it.
something like this does not work:
<input type="text" ..other attributes.. style="width:5em;border:solid #FF0000;">
Any help is appriciated.
And may I just add that my dojo version is old as dirt ( will be upgraded) but currently I can't take advantage of the newer features like dijit, etc.
Dojo uses templates for most of their widgets. The HTML code you write (with dojoType attributes and stuff) is nothing more than a placeholder to configure your widget. Inline CSS applied to this HTML will be applied to the top level of your widget.
Your widget usually consists out of multiple HTML elements and so it may happend that the CSS you write inline, will not be applied to the correct element. Also, Dojo indeed uses themes (wich you usually define as a class="themename" on a parent tag (usually <body>) and most default themes of Dojo are using !important CSS lines for various features.
The best way is to inspect what HTML elements are created when you use a widget and to define a style on that specific element. But because the CSS attributes of the Dojo themes are using !important, it's recommended to be more specific than what they define. The easiest way is to add a custom classname to the <body> tag, for example:
<body class="claro custom">
</body>
Then define your style like:
.custom .dijitTextBox > .dijitInputField {
background-color: yellow;
}
.custom .dijitTextBox > .dijitArrowButton {
background: red;
}
I also made an example JSFiddle.
Have a look at this thread - i think this could help you out:
Changing default style of DOJO widget
Regards
add !important to the end of your rules:
<input type="text" ..other attributes.. style="width:5em !important;border:solid #FF0000 !important;">
This should apply stuff to the input. Please check if the element isn't replaced when dojo starts using it and if you are applying the style to the correct element.

Resources