Can Reactjs programmatically handle :before? - css

I somehow have to programmatically set the width of the :before for a div.
<div className="something" style={someStyle}> </div>
How can I define the someStyle so that the width of the :before of .something``div can change accordingly??

Yes, you can programmatically change the value of pseudo-elements like ::before, ::after in react.
Here is a trick.
app.js
const widthVar = 34;
const someStyle = {
"--width": widthVar
}
<div className="something" style={someStyle}> </div>
style.css
.something:before{
width: var(--width),
// remaining code
}

Pseudo elements cannot be styled with inline styles as explained in https://stackoverflow.com/a/14141821/368697. You will have to style the something class name in a stylesheet with the .something:before selector. This is not a limitation of React but rather a design choice for HTML + CSS.
If you need to programmatically change the width of the pseudo :before element, it is probably more appropriate as a regular DOM element rendered by React.

I got insight from #am2505 to use CSS variables as it helped me however, this way avoids inline styling.
HTML
<div className="something"> </div>
CSS
:root {
--width: <yourDefaultValue>
}
.something:before{
width: var(--width),
}
JS
const changeWidth=() => {
let root = document.querySelector(':root');
root.style.setProperty('--width', '<yourNewValue>px');
call the function at the event you want the width to change.
The changeWidth function can be further modified to dynamically work with state using conditional statements.

Related

I want to apply a background image to the body of only one component

I am very new to React, so apologies for the mistakes in advance.
In my React app, say I have 2 components and as the CSS styles are global, it picks up CSS styles from all the files.
However, I wish to add a full background image to one of the components which I was able to achieve by using this code in my CSS file:
body {
background-image: url("../image.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
The problem is that the same image is also being applied to another component. I read a few answers and found that I can use ComponentDidMount hook and add the image to the body tag there. I tried that, but it doesn't show anything.
componentDidMount() {
document.body.style.backgroundImage = "url('../image.jpg')";
document.body.style.backgroundPosition = "center";
document.body.style.backgroundRepeat = "no-repeat";
document.body.style.backgroundSize = "cover";
}
EDIT
I realized I had the wrong wording for the question. What I mean to say is that I have two pages in React. For one of the pages, I want a full background image. However, because CSS styles are global, the background image is getting applied to all the pages.
You can use inline styling or specific styling by assigning a specific class or ID to the top element of one component.
INLINE STYLING Example:
// If Background variable has url to the background image.
const style = {
backgroundImage: `url(${Background})`
}
// in component use that inline style
return (
<div style={style}></div>
);
IF YOU WANT TO WORK with body only...
then add a class to body on component A mount and remove the class on component B mount. And attach the background property to the class.
A component usually return some jsx and in most cases a div. In other to apply a css to a single component I mean the jsx the component is rendering. you should define a css class, that apply a background image to the div the component is rendering and make the height of the div the window height. you can do this via inline css all
const MainDiv =()=>(
<div classname="testClass">
This will show background image in the covering the entire body
//Other content of your page can be added here like the rest of your page contents
<header>
This is my blog post
</header>
<nav>
this is my navbar
</nav>
</div>
);
ReactDOM.render(<MainDiv />, document.getElementById("root"));
.testClass{
backgroundImage :"url('../image.jpg')";
backgroundPosition :"center";
backgroundRepeat : "no-repeat";
background-size : "cover";
width: 100%;
height: 100vh
}

Apply stylesheet to half a page with shadow-dom?

Can I apply an external stylesheet to a specific div/element with shadow-dom or via any other means? I've heard about shadow-dom and I believe it lets you constrain your styles, but that's about all I know.
Specifically, I want half the page to use bootstrap, and the other half to use MUI or something else. This is just to show how my library works nicely with different themes.
I don't want to modify the CSS in anyway to constrain it to a specific element, nor do I want to use iframes.
Yes, you can apply an external stysheet in a Shadow DOM using the #import url CSS rule.
div.attachShadow( { mode: 'open' } )
.innerHTML = `
<style>
#import url( './external-style.css' )
</style>
<!-- other elements -->`
NB: The #import rule must placed at the top of the <style> element.
You can then manipulate the Shadow DOM like a normal DOM:
div.shadowRoot.appendChild( firstSection.cloneNode( true ) )
If your content is already existing in the normal DOM, you can move it with appendChild(), duplicate it with cloneNode() as in the above example), or reveal it with the help of <slot> element:
div1.attachShadow( { mode: 'open' } )
div1.shadowRoot.innerHTML = `
<style>
:host { display: inline ; background: #cfc ; }
::slotted( span ) { color: red ; }
</style>
<slot></slot>`
<div id=div1>
<span>Hello</span> world
</div>
In the last case you'll need to use the ::slotted pseudo-element to change the style of the original DOM, so maybe you'll have to modify already existing stylesheet. The best solution depends on your use case.

how to protect embedded div style not to be overridden by website style

I have div with its own style. I embedded this div on other website.
<div id="scoped-div">
<style>
label {
color: green;
}
</style>
<label> Scoped div </label>
</div>
But I face problem, my div style is overridden by website style. I don't want to use iframe. Except for the use of iframe is there any other way to protect my div style by external style changes?
Your request is exactly what Shadow DOM makes possible:
attach a Shadow DOM to the element you want to protect (here:
#scope-div),
put the HTML code you want to protect in the Shadow DOM,
clone it from a <template> element to get it easy (optional).
That's it!
var div = document.querySelector( "#scoped-div" )
var template = document.querySelector( "template" )
var sh
if ( 'attachShadow' in div )
sh = div.attachShadow( { mode: "closed" } ) //Shadow DOM v1
else
sh = div.createShadowRoot() //Shadow DOM v0 fallback
sh.appendChild( template.content.cloneNode( true ) )
<template>
<style>
label {
color: green;
}
</style>
<label> Scoped div </label>
</template>
<div id="scoped-div">
</div>
There is no way to fully protect your styles. But you can try the following:
Try to specify your elements selectors as specific as possible (e.g. with attributes and IDs)
Use inline styles
Use !important (but be careful with a broad use of importants)

Change style of pseudo elements in angular2

Is it possible to change style of pseudo elements using [style] or [ngStyle] in angular2?
in order to get a blur effect on a div acts like an overlay, and I should set up background-image on pseudo element.
I tried something like
<div class="blur" [style.before.backgroundImage]="'url('+ featuredImage[i] + ' )'">
it didn't work. I also tried this
<div class="blur" [ngStyle]="'{:before{ background-image:url('+ featuredImage[i] + ' )}}'">
You can achieve what you need with CSS variables.
In your style sheet you can set the background image like this:
.featured-image:after { content: '';
background-image: var(--featured-image);
}
After that you can programmatically set this variable on the same element or higher up in the DOM tree:
<div class="featured-image" [ngStyle]="{'--featured-image': featuredImage}">
More about CSS variables here: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables Note that the browser support is not complete yet.
Also note that you will need to sanitize the url/style using sanitizer.bypassSecurityTrustResourceUrl(path) or sanitizer.bypassSecurityTrustStyle('--featured-image:url(' + path + ')')):
No it's not possible. It is actually not an Angular issue: pseudo elements are not part of DOM tree, and because of that do not expose any DOM API that can be used to interact with them.
Usual approach if you want to deal with pseudo elements programmatically is indirect: you add/remove/change class and in CSS make this class affect corresponding pseudo-element. So in your case you could have one more class that changes necessary style:
.blur:before {/* some styles */}
.blur.background:before {/* set background */}
Now all you need to do is to toggle .background class on the element when you need before pseudo-element to get a background. You can use NgClass, for example.
if you want to add other properties I did it like this:
<div class="progress" [style]= "'--porcentaje-width:' + widthh " ></div>
and the css:
.progress::after {
content: '';
width: var(--porcentaje-width);
}
this worked for me :)
With current versions of Angular 2+ you can use CSS Variables to achieve this as well as sanitizing your input.
In your style sheet define the rule using CSS Variables. A fallback can also be defined as CSS Variables aren't supported by IE.
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
.featured-image:after {
content: '';
// Fallback for IE
background-image: url('fallback-img.png');
background-image: var(--featured-image);
}
Rather than bypassing security trust style, you can also sanitize your input with a reusable pipe:
https://angular.io/api/platform-browser/DomSanitizer#sanitize
import {Pipe, PipeTransform, SecurityContext} from '#angular/core';
import {DomSanitizer, SafeStyle} from '#angular/platform-browser';
#Pipe({
name: 'safeStyle',
})
export class SafeStylePipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: string): SafeStyle {
if (!value) return '';
return this.sanitizer.sanitize(SecurityContext.STYLE, value);
}
}
In your template:
<div class="featured-image" [style.--featured-image]="featuredImage[i] | safeStyle"></div>

Set the css property of a class based on its visibility property using CSS only

I have a set of div whose visibility is set to either hidden or visible. Based on this css visibility property i need to add the css property on those div, like
<div class="div-class" style="color:#ff0000; margin: 0px 10px; visibility:hidden;">
[Block of Code]
</div>
Now i need to define the following in style.css file.
.div-class:visible {top:10px;left:50px;}
.div-class:hidden {top:0px;left:0px;}
Is this possible???
yes with css attributre selectors you can do it
try the below css:
.div-class[style*="visible"] {
color: green;
}
.div-class[style*="hidden"] {
color: red;
}
What you are trying to do is not "really" possible.
I mean it's ill thought by design in the first place.
Even Vamsikrishna's solution might not work as expected.
If you set the overflow property to hidden via javascript or inline styles, the .div-class[style*="hidden"] rule will apply since the style attribute will contain the hidden string.
Moreover , setting inline styles on html elements is bad practice itself in most cases.
I suggest you try and learn css principles a little more.
I'd do the following:
HTML
<div class="div-class div-hidden">
[Block of Code]
</div>
CSS
.div-class {color:#ff0000; margin: 0px 10px; top:10px;left:50px;}
.div-hidden {visibility:hidden;}
.div-class.div-hidden {top:0px;left:0px;}
Then you can use javascript to toggle the "div-hidden" class.
You can do something using attrchange - a jQuery plugin ,
like this:
Add "attrchange" script into HTML page like
In Javascrip catch event
var email_ver_input = $("input#email_ver_input.verifyInput");
email_ver_input.attrchange({
trackValues: true,
callback: function (event) {
if (email_ver_input.is(":visible")){
$("#inputcode_wrap").show();
}
}
});

Resources