How is it possible to adjust a component's CSS based on a global CSS class-name in Angular? - css

We are using a class on the html-element to determine whether the user is in dark or light mode of the app.
<html class="dark-mode"></html>
This class is added using Renderer2 in a service that detects the selected setting of the user. This works fine so far.
Now, we have to adjust all the components to look good in the dark mode as well. But the problem is Angular's ViewEncapsulation.
What we thought would come in handy, is to simply update the SCSS of the component:
.headline {
color: black;
.dark-mode & {
color: white;
}
}
Or in plain CSS:
.headline {
color: black;
}
.dark-mode .headline {
color: white;
}
Now this doesn't work, because the class .dark-mode seems to be encapsulated, as expected.
How can we solve this problem?

:host-context provides access to css classes above the :host. By using :host-context you are able to check if any of the parents of the host have a specific css class and apply styling:
:host-context(.dark-mode) h2 {
color: white;
}
Documentation: https://angular.io/guide/component-styles#host-context

Related

Simple SASS modules classes can’t work together for specificity

I want to be able to not have to use !important and instead simply resolve by just using more specific selectors. Take this element for example:
<div>
<p className={`${headerStyles.headerOuter} ${bodyStyles.something} ${otherStyles.another}`}>Test</p>
</div>
It uses three classes each defined in separate css modular files:
import headerStyles from ‘…’
import bodyStyles from ‘…’
import otherStyles from ‘…’
Let’s say that headerStyles.module.scss contains:
.headerOuter {
color: blue;
}
bodyStyles.module.scss contains:
div .something {
color: red;
}
And otherStyles.module.scss contains:
.another {
color: green;
}
The p will have red text since bodyStyles is more specific.
But I want to be able to do this in headerStyles.module.scss:
.headerOuter {
&.another {
color: blue;
}
}
// or .headerOuter.another
So that headerOuter and another can work together to be higher in specificity than bodyStyles to force the element to apply blue text. But the problem is that headerStyles and otherStyles don’t seem to be able to recognise each other.
How can this be fixed?
I’ve made a similar demo here, where the text should be black but it’s not: https://codesandbox.io/s/css-modules-react-forked-mxtt6 - see another.module.scss and the text should be black
Thank you
From the codepen
The color: black selector is:
._src_another_module__another._src_another_module__something
While the actual element's classes are:
_src_test_module__test
_src_sassy_module__something
_src_another_module__another
The second element's class contains "sassy", it is different from the selector, that's why it doesn't match.
You can check it with the DevTools. The blue and red styles are shown as overwritten, the green has more specificity, but the black one doesn't even apply for the element as shown in the picture below.
Edit
I think there is lack of information about the actual tool behavior or just
a misunderstanding. The way it builds the name is _src + _<file_name> + _<selector_name>.
That being said:
/* The final style from "another.module.scss. */
._src_another_module__something {
color: red;
}
._src_another_module__bling {
background: #eee;
font-family: sans-serif;
text-align: center;
}
._src_another_module__bling button {
background: red;
}
._src_another_module__another {
color: blue;
}
._src_another_module__another._src_another_module__something {
color: black;
}
Notice the #import './sassy.module.scss' has nothign to do with the black stuff, it just duplicates the style with a different naming.
<!-- The final element with it's classes. -->
<p class="_src_test_module__test _src_sassy_module__something _src_another_module__another">
test
</p>
Note: all this code comes from the codepen.
Text isn't black because you are including the selector something from the import of sassy.module.scss with the ${style.something}, therefore the class will be named as _src_sassy_module__something (which is the red one).
If not yet, I encourage you to check the results with the DevTools often.
<p className={`${testStyles.test} ${styles.something} ${anotherStyles.another}`}>test</p>
The reason it is not working is that the latest calssname which is another is being called and it dosent effect what you do with the previous classes that are added to the element which here is something. In the scss file another.modules.scss you are importing the sassy.module.scss, this updates the style on the class something but dosent effect the style on the latest class another.
`#import './sassy.module.scss';
.another {
color: blue;
&.something {
color: black; // should be black
}
}

How to stop inheritance of CSS applied to global scope inside Angular's Emulated Encapsulation?

We have an Angular Application inside an ASP.NET MVC View,
So inside .cshtml we have this:
<app-root></app-root>
There are styles applied to the entire ASP.NET app which are colliding with the Angular components. Note that, Native ShadowDom encapsulation is not an option for me due to it's limited support of browsers.
I am limiting the scope by having the styles applied to each component (Emulated version),
Assume this is my ASP.NET view with it's own set of styles/stylesheets specified as below and there is <app-root></app-root> is where I am having my app which holds other components, I want to stop the styles in the style tag to bleed over my app-root. How can I achieve this?
<body>
<style>
body {
background-color: powderblue;
}
h1 {
color: blue;
}
p {
color: red;
}
</style>
<app-root></app-root>
</body>
You can either not timport the global stylesheet or you can overrwrite those global styles. Since these rules are written as global, they must be overwritten in some way. (They can’t be ignored).
Eg.
body {
background-color: white;
}
h1 {
color: black;
}
p {
color: black;
}

ngx-charts-gauge title color is unable to modify

I'm trying to add ngx-charts-gauge on angular5 app page.
Following these : https://swimlane.gitbooks.io/ngx-charts/content/charts/gauge.html
Everything works fine except I don't find any way or attribute or info to change Big center title color...It stills black !
I tried to override css class...with no chance.
.chart-container {
color: white;
}
Any help would be appreciated.
Thanks.
Change your css as below it will work
:host /deep/ .chart-container {
color: white;
}
OR
:host ::ng-deep .chart-container {
color: white;
}
Reason: Component style only applies to the html in component.
To force a style down to the child component use /deep/
documentation, another reference

How to change Polymer(1.0) paper-toolbar background colour?

Yesterday I decided to try Polymer 1.0 and I'm already facing difficulties when trying to styling the paper-toolbar.
The documentation says that the background colour can be changed by using:
--paper-toolbar-background
But how can I use it on CSS?
I tried the following:
paper-toolbar {
--paper-toolbar-background: #e5e5e5;
}
Also this:
paper-toolbar {
--paper-toolbar {
background: #e5e5e5;
}
}
But neither worked. What is the correct way to do it?
Thanks.
If you are styling it on your main page, then you have to apply styles using <style is='custom-style'>. This is to make Custom CSS Properties work.
Applying is relatively easy. paper-toolbar provides 2 custom properties and one mixin. --paper-toolbar-background is a property that changes the background color of the toolbar while --paper-toolbar-color changes its foreground color. --paper-toolbar is a mixin applied to the toolbar.
To use these properties is just the same as applying styles in your elements. As an example
<style is="custom-style">
paper-toolbar {
--paper-toolbar-background: #00f; /* changes the background to blue*/
--paper-toolbar-color: #0f0; /* changes the foreground color to green */
--paper-toolbar: {
font-size: 40px; /* Change default font size */
}; /* Notice the semicolon here */
}
</style>
I couldn't find a solution to this problem either until recently. I have two toolbars and I didn't want to change the CSS for all toolbars just the header toolbar.
To change the CSS for every toolbar, in your external css file add the following:
paper-toolbar.paper-toolbar-0 {
background: orange;
color: red;
}
However, that doesn't address the problem. To change a single paper toolbar based on a class like the following:
<paper-toolbar class="header">
...
</paper-toolbar>
The above uses the class called "header" so in my CSS I added:
paper-toolbar.header {
background: orange;
color: red;
}
... and it worked! Yay! That means with this you should be able to override any CSS of any of the other elements doing the same thing. This is completely untested but I think it should work like:
<elementName>.<classname> {
...
}
Hope this all helps!

Less - Defining a class name that conflicts with mixin

The problem that I've got is quite simple. I want to use a css class name that has been previously defined as a mixin.
I'm currently using Bootstrap, which has defined a mixin called "placeholder", and because of backwards compatibility we're planning to use the jQuery placeholder plugin to support placeholders for IE 9. The problem is that this plugin adds the css class "placeholder" to the DOM element.
How do I define the css class "placeholder" in my LESS file without executing the mixin previously defined in Bootstrap?
This should not be a problem. This is bootstrap's placeholder mixin
// Placeholder text
.placeholder(#color: #input-color-placeholder) {
&:-moz-placeholder { color: #color; } // Firefox 4-18
&::-moz-placeholder { color: #color; // Firefox 19+
opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526
&:-ms-input-placeholder { color: #color; } // Internet Explorer 10+
&::-webkit-input-placeholder { color: #color; } // Safari and Chrome
}
This is not a mixin class, as it has parenthesis after it. Therfore it will not output anything unless it is referenced. To use this I would need to do something like this.
.input {
.placeholder;
}
Therefore this will not interfere with any .placeholder class you may have.
.placeholder {
color: red;
}
The two should happily co-exist and you should not get any problems.
Edit: see comments
The solution was to use multi class selector to overcome the issue.
Example
.input.placeholder {
color: red;
}

Resources