host + ng-deep + body css not applied - html

I'm trying to make a background color for a specific component being display in the whole component page.
It's working fine with
\ ::ng-deep body
background-color: red
But the things is when i do it like that, the body css is bleeding to the other component page, which become red too.
So what i really want to do, is making it local with host.
I tried to use
\:host ::ng-deep body
But it wasn't working too, the body background did not change color until i add a specific body tag to my html file component.
But i don't want to add a body tag because when i do this, the body size is limited to the element in the page.
I also try to use ViewEncapsulation, but it messed up with all my css.
Any help would be appreciate.

Your first issue (As you found out) with ng-deep is that it bleeds into other pages. And because CSS is lazy loaded inside Angular, everything will be fine until you go to that page, and then head to another page and suddenly everything will be red.
Your second issue is that the :host pseudo selector isn't saying "For this page only" it's saying "For everything inside this component".
So as an example :
If I have a component called MyComponent, and I have css like :
:host ng-deep div {
background-color :red;
}
And I have a template like so :
<body>
<app-mycomponent>
<div></div>
</app-mycomponent>
<app-secondcomponent>
<div></div>
</app-secondcomponent>
</body>
Only the div inside app-mycomponent would be red. The div inside app-secondcomponent would not be read. Again, :host allows you to ng-deep only within that component.
So why would you need this? Generally it's because you may use a library that you want to style, so you can place it inside a wrapper component and use ng-deep commands freely with the :host prefix, so only the library component inside that wrapper is styled and the rest of your application is unaffected.
So what's the solution? Well the other issue you have is that the <body> tag is actually outside the scope of your angular app. Typically when I've had to edit the body/html tags as a whole, I've just used plain old javascript.
So for example :
export class AppComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
document.body.style.backgroundColor = 'transparent';
}
ngOnInit(): void {
document.body.style.backgroundColor = 'red';
}
}
It's not the nicest thing in the world, but it's also not terrible. I mostly have to do this when creating modal components that want to stop the body scrolling etc.
For more reading on NG-Deep bleeding : https://tutorialsforangular.com/2020/04/13/the-dangers-of-ng-deep-bleeding/
And how :host works : https://tutorialsforangular.com/2019/12/24/using-the-css-pseudo-element-host-in-angular/

Related

Cursor code, not showing the custom cursor set. CSS

pretty new to CSS and HTML and was hoping somebody could help me fix this. I wanted to be able to change the icon for the cursor although when I run the code, simply no change. A few visits to chatGPT hasnt done me much either. Here's my code:
body2 {
cursor: url("assets/img/wiiu/Smile_icon_32x32.png"), url("assets/img/wiiu/cursor.svg"), auto;
}
And yes, it is 32x32.
I've tried moving it to different classes, changing words, changing everything. Although nothing has worked.
here is a good reference: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor?retiredLocale=de
So basically you try to applie to a body2 HTML element you're CSS code. If its a class try the CSS selector .body2 {} or in the case its an id of a HTML element #body2 {}.
In you're css you've got one main picture and the second one as fallback. Just make sure you set the correct path corresponding to the location of you're CSS file.
To ensure that, you can also try the full path instead of the relativ one like C:\Users\xxx\Smile_icon_32x32.png
You are using the wrong css declaration, your code will only work if you have defined a custom html element having <body2> as tag.
What you probably want is:
body { ... }
applied to <body> tag
or a css class
.body { ... }
applied to or any other tag having body as class.
or a css id
#body { ... }
applied to or any other kind of tag with body as id.
Alternatively check in the browser console if the rule is applied and if the image path is resolved correctly.
Here is an example where http://example.com/32x32/990000/fff.png&text=PNG don't exist and https://dummyimage.com/32x32/009900/fff.gif&text=GIF exist so the gif will be used instead of the png :
.body2 {
display:inline-block;
cursor: url("http://example.com/32x32/990000/fff.png&text=PNG"),url("https://dummyimage.com/32x32/009900/fff.gif&text=GIF"), auto;
}
<div class="body2">display</div>

Can you set body id dynamically in React?

I am trying to implement dark mode in my app.
The idea is to add this to the root element:
<div id="dark">
And then this in CSS:
#dark {
background-color: #1A1A2E;
}
And then in Css, customize each dom element by using classes. For example, here I will work on cards:
#dark .card-body {
background-color: #16213E !important;;
}
#dark .card-header {
background-color: #0F3460 !important;
}
Now, this works perfectly fine.
But, with Modals, it does not work. I think it's because Modals are not rendered initially so for some reason the dark style does not apply to them.
What worked though is adding id="dark" to each modal:
#dark .modal-header {
background-color: #0F3460 !important;
}
#dark .modal-body {
background-color: #16213E !important;;
}
#dark .modal-footer {
background-color: #16213E !important;;
}
<Modal
// dark doesn't get applied automatically for modals because apparently modals are not rendered in the beginning
id="dark"
isOpen={this.state.isModalOpen}
toggle={this.toggleModal}
>
<div className="modal-header">
But, it'll be a pain to apply this to every single modal.
One solution mentioned here:
Modal should be the descendant of a tag which has id="dark". It is
loaded by the script right below the script tag and you are trying to
put 'dark' id on some div tag and the modal doesn't lie inside it,
thus the CSS selector not targeting it.
So, you need to put id="dark" on the body tag.
This solves the modals issue.
But, the problem is in my original implementation of dark mode, I am controlling that id in the root component like this:
// Root component
<div id={this.state.should_enable_dark_mode ? "dark" : "default"}>
And should_enable_dark_mode is managed like this:
manageDarkMode() {
window.addEventListener("storage", () => {
console.log("change to local storage!");
let should_enable_dark_mode = localStorage.darkMode == "true";
this.setState({
should_enable_dark_mode,
});
});
}
So the problem with the solution mentioned above is that I couldn't find a way to control the body tag from the react app. And I am not sure if it's a good thing to do.
What do you think I should do?
I see in the comments to your original question that you decided to just modify the body element in the browser DOM, which will probably work fine since the body element is not controlled by React and will likely not be changed by any other code.
I would however like to suggest a few improvements that makes it at bit less dirty:
use a data attribute like data-display-mode="dark" as a target for your CSS selectors instead of the ID. IDs are supposed to be stable and other tools and libraries (e.g. UI test tools) might rely on this.
use the Modal.container property to attach your Modals to the App element (the React-controlled global parent div defined in your React code, which you can control, not the app-root-div in index.html). Then set your data-display-mode attribute here by React-means. This way you will not bypass the virtual DOM.
use CSS custom properties for defining your colors, and then define all dark mode modifications in one place. Don't spread your dark-mode-styling code across multiple class selectors - you will have a hard time maintaining this.

StencilJS - Why do some styles (e.g., background-color) apply to all elements when styling container?

I'm using Stencil JS to write components for a micro front-end I'm building. I have a <dashboard-container> that as the name suggests, holds all the other components I have.
I'm trying to change the background color of my index.html's body and then let every other element, component keep their own style.
The problem is that if I try to apply background-color: red to my <dashboard-container>, the rest of the children also inherit the background color.
I'm expecting that if I apply a background color to a parent element, the children keep their own styles but it's not working that way.
How can I style a component without the children inheriting it?
This is how I have it set up:
import { Component, h } from '#stencil/core';
#Component({
tag: 'lh-dashboards-container',
styleUrl: 'lh-dashboards-container.scss',
scoped:true
})
export class LhDashboardsContainer {
render() {
return (
<div class="lh-dashboards-container">
<lh-dashboards-navigation></lh-dashboards-navigation>
<lh-dashboards-cohort-finder></lh-dashboards-cohort-finder>
</div>
);
}
}
So, if I do the following:
//lh-dashboards-container.scss
.lh-dashboards-container {
background-color:red;
}
Every child component and their element within will have their background changed to red.
You can add all: initial; on the child elements but it will specify that all the element's properties should be changed to their initial values.
It's better to style the children, to override the ones being inherited from parent, if needed.
You can read more about all here.

CSS selector for an :after element if body has class

I'm desperately trying to hide an automated added image on a checkout page.
I'm trying to select the element div.panel-body:after which is on a page that has a body class.
I've tried:
body.offer-checkout-offer-311523 div.panel-body:after {
display: none !important;
}
div.panel-body is not a direct child of body that's why I used a space between the selectors instead of > But despite my attempts, the image does not hide.
Any clue?
Edit:
the HTML element I'm trying to edit:IT's the ::after I'm trying to target
HTML code
I've tried to export the whole path to the element but...
Edit2:
This is my website, It's probably easier if I show the page here: photoserge.com/offers/yDBpDfqi/checkout?coupon_code=FBPSQS
I'm trying to hide the credit card images but only on this page. The whole site uses the same checkout page thats why I'm trying to target only this specific instance.
Maybe try:
.checkout-panel .panel-body::after{
display: none
}
I just tried by inspecting the page.
Also, if you want to target this specific page. You will have to remember to add the css to only this page, and not add this code to a global css file.

First dynamically added component not getting styling from a class

I have a big list of dynamically added components and all of them are getting styling from the css class except the first one. It's specifically a darkmode or litemode class that gets added depending on the if this.state.dark === true or not
here's the function that renders them
renderComponent(info) {
return <Info isDark={this.isDark()} isHidden={this.state.hide === true} user={info} key={info} />
}
and this is what calls that function
{info.map(this.renderComponent)}
css class that's not rendering on first component
.darkmode + .other-class {
background-color: rgb(131, 21, 21);
}
I've tried conditionally rendering the page into a separate version with just darkmode and using the classes directly everywhere(ie there's no way they don't have the class).
In inspect element it says they have the class and even styling from a different area in the css is being applied. but the background stays transparent on just the first element.
I've also tried adding the class in the component itself and it's always the exact same result.
https://i.imgur.com/vLa8Tn9.png picture of the element not loading the css
https://i.imgur.com/cJxT5bU.png picture of element that is loading the css
I think this is a problem with your CSS selector.
The plus (+) sign select and style every element that is placed inmediately after the first element in your CSS selector.
In W3School you can see this behaviour
I think what you are trying to do is this:
.darkmode.Offline {
background-color: rgb(131, 21, 21);
}