I am migrating an application from AngularJS to Angular. I have just moved a loading-indicator component to Angular, and that has an optional modal binding to say whether its a modal loader or not.
In reality this doesnt bind to anything right now, it simply matches a CSS rule.
HTML
<loading-indicator [modal]="true"></loading-indicator>
SCSS
loading-indicator {
&[modal="true"] {
background: rgba(255,255,255,0.5);
}
}
The SCSS above targets an attribute of modal not [modal].
How do I target [modal]? I saw some answers suggesting I can escape the brackets using \\ e.g. &\\[[modal\\]] but this didn't seem to work.
You cannot. Because [modal]="true" for Angular it's an input and this will be converted to another HTML attribute.
You can use modal=true in your component and you can select this with
[modal=true] {
/*styles*/
}
But for encapsulation, you need to put this style on the root styles of the app.
It's a better solution to bind the input modal value to a [ngClass]="":
Inside the component ts loading-indicator:
#Input() modal;
On the template use:
<div [ngClass]="modal ? 'modal-background' : ''"></div>
On the styles of component:
.modal-background{
background: rgba(255,255,255,0.5);
}
Let's assume that the user can add styles for every component in admin panel and I get it as string in my Node server:
const stylesFromAPI = ".p { color: red } .bg { background: lime }";
How to prefix this styles before append to my document to avoid conflicts?
I need something like CSS modules but working with strings (not as module loader):
const stylesFromAPI = css(".p { color: red } .bg { background: lime }"); // returns hashedClassname685946898456
<SomeCompontent className={stylesFromAPI} />
produces:
<style>
.hashedClassname685946898456 .p { color: red }
.hashedClassname685946898456 .bg { background: lime }
</style>
<div class="hashedClassname685946898456"></div>
Shadow DOM seems like a reasonable option here. You can create your style tags with inside the shadow DOM without having to deal with any selector prefixes. For example, using the react-shadow package:
import root from 'react-shadow';
Then in JSX, something like:
<root.div>
<style type="text/css">
{/* CSS string here */}
</style>
<div>
{/* Stuff here */}
</div>
</root.div>
Check out a working example of this here: https://github.com/joshdavenport/stack-overflow-61566764-react-css-shadow-dom
The main downside here is your styles from outside the shadow DOM will not apply. Those using the shadow DOM for components see this as a good thing, those simply trying to scope CSS do not. Not sure what it is you're scoping, so I can't really tell if that would be an issue for you.
If it is, you could re-import your styles within the shadow DOM, though I can't really point out how to do that without knowing what bundler is in use and how it is in use.
Alternatively you could pull apart your imported CSS using the css package, iterate over the selectors prefixing all with a randomly generated class, and then re-stringify.
I'm working on a ReactJS app that has a header at the top, a menu on the left, and the "frame" in the middle is where routes and their corresponding components are loaded. I want to be able to apply a CSS stylesheet to specific components only when they are loaded. I also don't want them applied all the time or to the top header or left menu.
My expectation was that adding import 'custom.css'; to a specific component would only apply the stylesheet's styles to that component and it's children when the route is active. Instead, it applies it to the entire page even when the route/component are not loaded.
I understand that an alternative approach is styled components, but, for my use-case, a design company is supplying a stylesheet (which should remain unchanged) that we need to consume only for the sub-module I'm working on and I don't want its styles to affect the rest of the app.
How can I have a stylesheet only applied to my active route/component?
Use simple CSS technique. Suppose you have two components with different css files (say about.css and contact.css). Now consider your both CSS file have one common class with different style properties, like:
about.css
.container{
max-width: 400px;
}
contact.css
.container{
max-width: 500px;
}
Yes in ReactJS both the CSS files will load at the same time and will override any one of the style. so to solve this problem add class to differentiate this styles, like:
about.css
.about-component.container{
max-width: 400px;
}
contact.css
.contact-component.container{
max-width: 500px;
}
If you want apply only when the component is mounted, you can use the lifecycle.
The follow example is based in the idea you are using sass, React, sass-node and have the loaders into webpack.
<pre>
import React from 'react';
import './styles.scss';
class MyComponent {
constructor(props) {
super(props);
this.state = { className: '' }
}
componentDidMount() {
this.setState({
className: 'myOwnClass'
});
}
render(){
return (
<div className={this.state.className}>This is a example</div>
);
}
}
export default myComponent;
</pre>
To be able to only call that specific CSS when you need it you can use CSS Modules. You may need to update your version of react.
When saving your CSS file save it with a ".module.css" eg. "styles.module.css". The CSS in these files can only be used and accessed by hte components where are they are imported. As stated in a tutorial from W3Schools.
Let's say this is your CSS code in styles.module.css:
.container {
color: white;
}
.cont-child {
background-color: red;
}
Then in your JS file you can import the CSS file like this if the JS and CSS files are in the same directory. Make sure you point to the correct path.
import styles from './styles.module.css'
Then in your HTML section you can use it like this:
class Home extends React.Component {
render() {
return(
<main className={ styles.container } >
<div className={ styles["cont-child"]} >
Some div text about something...
</div>
</main>
);
}
}
I currently use both ways to access the selectors, since the styles variable acts like an object. I placed both of them here because the second option is capable of fetching selectors named like "btn-active". Which comes in handy in some situations. Camelcasing is considered cleaner though.
Please note: I originally posted this answer as a reply to a similar question here React CSS - how to apply CSS to specific pages only
I want to be able to apply a CSS stylesheet to specific components
only when they are loaded.
Why not apply the styles inline via React.js?
Step 1. Create the style object for the component:
var componentOneStyle = {
color: 'white',
backgroundColor: 'red'
};
Step 2. Populate the component's style attribute with the style object:
ReactDOM.render(<div style={componentOneStyle}>This is Component One</div>, mountNode);
Does anyone know how can I change mat-spinner color in Angular Material?
Overriding css doesn't work. I tried changing color in material files but they can only be imported, I can't change anything there.
I want it to be my custom color, not color from prebiult-themes.
Use this code for ** < mat-spinner >** add this code in your .css file
.mat-progress-spinner circle, .mat-spinner circle {
stroke: #3fb53f;
}
This answer will work for those who're looking for a flexible solution in Angular 4 / 6 / 7. If you wan't to change the color of a mat-spinner at a component level, you'll need to use the ::ng-deep selector. Knowing this, the solution is quite easy.
In your html file:
<div class="uploader-status">
<mat-spinner></mat-spinner>
</div>
In your css / scss file:
.uploader-status ::ng-deep .mat-progress-spinner circle, .mat-spinner circle {
stroke: #000000;
}
Notice that the .uploader-status css class encapsulates the component. You could just use ::ng-deep without using a class but then whatever changes you're doing to the mat-spinner will appear in other areas of the application. Check this to learn more.
Easy Fix!
Add custom css rules inside styles.css instead of component.css file
.mat-progress-spinner circle, .mat-spinner circle {
stroke: #2A79FF!important;
}
To your .css/.scss component file style add (it will works locally - in component only)
:host ::ng-deep .mat-progress-spinner circle, .mat-spinner circle {
stroke: #bada55;
}
If you don't want to mess around with the global css and need a way to set the spinner to different colors in different areas of your app, I would strongly recommend to create a directive for it.
import { Directive, Input, ElementRef, AfterViewInit } from '#angular/core';
#Directive({
selector: "[customSpinner]"
})
export class CustomSpinnerDirective implements AfterViewInit{
#Input() color: string;
constructor(
private elem: ElementRef
){}
ngAfterViewInit(){
if(!!this.color){
const element = this.elem.nativeElement;
const circle = element.querySelector("circle");
circle.style.stroke = this.color;
}
}
}
Then the spinner should work like this:
<mat-spinner diameter="22" customSpinner color="#fff"></mat-spinner>
mat-spinner html code :
<mat-spinner color="accent" diameter="20" class="loading"></mat-spinner>
And now sass code :
.mat-spinner {
::ng-deep circle {
stroke: #33dd82;
}
}
Color is build in.
Theming
The color of a progress-spinner can be changed by using the color property. By default, progress-spinners use the theme's primary color. This can be changed to 'accent' or 'warn'.
https://material.angular.io/components/progress-spinner/overview
example
<mat-spinner color="warn"></mat-spinner>
I think the key here is that is must be in the GLOBAL styles.css file. The below solution does work if placed there (should be the CSS file affected when material was added to the project if added with ng add:
.mat-progress-spinner circle, .mat-spinner circle {
stroke: #b68200;
}
Of course you could also add classes to the component and specify different selectors if you want distinctly styled spinners. However, it seems the classes must be in the global CSS file.
Late to the game, but this worked well in my .scss file today...
.parent-element-class {
::ng-deep
.mat-progress-spinner,
.mat-spinner {
circle {
stroke: white;
}
}
}
In your styles.css file, add...
::ng-deep .mat-progress-spinner circle, .mat-spinner circle {
stroke: #2A79FF!important;
}
As you might have guessed, I have just made a simple modification to Nitin Wahale's answer. I have prefixed his answer with ::ng-deep and it worked in my case as I had the same issue.
I hope this helps somebody
By default angular material would give your spinner default color of primary.
You can use 3 colors available in pallet that would be primary, accent, warn.
However, if your needs are of different color please consider anyone of the below options.
Easy way(not recommended)
You can use any of method to override css forcefully mention in other answers. I would recommend using parent class above spinner element if you do not want spinner to be of same color throughout the application.
The correct and recommended approach would we to use custom-theme for material. If you already have custom you can just
do like creating a custom mixin called
//here $primary-color is the color you want your spinner to be
#mixin spinner-custom-theme($primary-color, $accent-color, $warn-color) {
$custom-spinner-theme-primary: mat-palette($primary-color);
$custom-spinner-theme-accent: mat-palette($accent-color, A200, A100, A400);
$custom-spinner-theme-warn: mat-palette($warn-color);
$custom-spinner-theme: mat-light-theme($custom-theme-primary, $custom-theme-accent, $custom-theme-warn);
#include mat-progress-spinner-theme($custom-spinner-theme);
}
Now go to file where #include angular-material-theme($custom-theme);
is written
and #include your mixin just below the #include angular-material-theme($custom-theme);
To know more on how to create custom theme you can check this blog here
Sample Color, strokeWidth, diameter and title
<mat-spinner strokeWidth="24" [diameter]="85" color="warn" title="Tooltip text here"></mat-spinner>
In your css file mention like below:
::ng-deep.mat-progress-spinner circle,.mat-spinner circle {stroke: #f2aa4cff !important;}
Here, ::ng-deep will be used to force a style.
!important here what says is that "this is Important",you ignore all other rules and apply this rule.
.mat-mdc-progress-spinner { --mdc-circular-progress-active-indicator-color: white; }
This worked for me using Angular 15.
This is best achieved by doing a custom theme.
https://material.angular.io/guide/theming
use this code
<md-progress-circular md-diameter="20px"></md-progress-circular>
md-progress-circular path {
stroke: purple;
}
In case you guys want to customize each spinner on your webpage. You can do it this way:
svg .mat-progress-spinner circle, .mat-spinner circle {
stroke: inherit;
}
And now on mat-spinner add class:
<mat-spinner class="custom-spinner-color"></mat-spinner>
And in css file:
.custom-spinner-color {
stroke: #234188;
}
That was what I wanted to achieve. I suppose if you look for this question you probably want the same.
Mat progress spinner custom timer, I changed to 3 different colors based on the value passed to mat spinner. Pls refer : https://material.angular.io/components/progress-spinner/examples
<mat-progress-spinner class="mat-spinner" [color]="progressColor"
[diameter]="170" [strokeWidth]="14"[mode]="'determinate'"
[value]="progressLabel">
</mat-progress-spinner>
Ts file
timer: number = TIMER; // say 60 seconds
progressColor: ThemePalette = 'accent';
timerPercent: number = 0;
progressLabel: number = 100;
startTimer() {
this.timer = TIMER;
this.timerInterval = setInterval(() => {
if (this.timer <= 0) {
clearInterval(this.timerInterval);
this.timerFinish();
}
if (this.timer > 0) {
this.progressColor =
this.timerPercent > 69
? 'warn'
: this.timerPercent > 49
? 'primary'
: 'accent';
this.timer--;
this.timerPercent = (100 * (TIMER - this.timer)) / TIMER;
this.progressLabel = 100 - this.timerPercent;
}
}, 1000);
}
For me this is how I do it clean without messing with anything globally:
in my .css
::ng-deep .customColorSpinner circle {stroke: #4e1e1e!important;}
in my .html
<mat-spinner class="customColorSpinner"></mat-spinner>
You can use a custom Angular Directive to solve this problem. The directive allows you to set a custom color on the mat-spinner like this:
<mat-progress-spinner spinnerColor="#09ff00"></mat-progress-spinner>
I have an article here where I explain this and thoroughly show you how to solve it
In component.scss where your mat-spinner exists, just add this :
::ng-deep .mat-mdc-progress-spinner {
--mdc-circular-progress-active-indicator-color: #7D469A;
}
I need to dynamically change the color in the react component for specific selector.
In scss (use sass) i have the following rule:
foo.bar.var * {
color: blue;
}
I want to change it in react code, to be yellow, red or something else.
I cant use style property for element, cause i need the selector to
apply for all subchilds !=)
Is there any native ways? Or should i use Radium? Or is there any similar libs for this? Maybe css-next some hove can help with this?
I have color picker, i cant write class styles for every color =(
For some answerers NOTE:
So i have selector in some scss file, that imported in some root js file with .class * {color: $somecolor} and i need change the $somecolor in that selector, during picking colors in color picker
Maybe i can somehow set selector for all nested inside style property? or there is the way how to recursively apply css style for every nested items from the style prop?
What about
class MyComponent extends React.Component {
render() {
const yellow = true // Your condition
return(
<div className={`foo bar var ${yellow && 'yellow'}`}
My item
</div>
)
}
}
.foo.bar.var {
& * {
color: blue;
}
&.yellow * {
color: yellow;
}
}
You could define a custom CSS property (CSS variables) using the style attribute of the element and assign the value to a prop, state etc.
<div className='foo bar var' style={{ "--my-color": props.color }}></div>
The custom property would work for any selector that apply to that component or children. So you could use it like that:
foo.bar.var * {
color: var(--my-color);
}
See a snippet with similar code here
this may sound stupid . but does this work ?
import myCss from './mydesign.css';
myCss.foo.bar.var = "your color"