How can I get the position of a component without using GetElementById or getBoundingClientRect?
I'm using react/JSX to render components one inside of each other, and I'm trying to get the distance between the top of the parent and the bottom of the child, if I use that functions I need to wait until the child is rendered and I need to do the calculations on the parent
here is a sample code of what I'm doing
export function TestPage() {
return <BaseObject />;
}
function BaseObject() {
return (
<div
className="popBox"
style={{ top: "100px", left: "100px", width: "500px", height: "500px" }}
>
<div
className="popBox2"
style={{ top: "150px", left: "150px", width: "200px", height: "200px" }}
></div>
</div>
);
}
and the css
.popBox
{
background-color: #4F8989;
position: sticky;
}
.popBox2
{
background-color: #89694f;
position: sticky;
}
Here's an example of using the useLayoutEffect and useRef hooks to grab refs to the real DOM elements and querying their measurements.
function BaseObject() {
const ref1 = React.useRef();
const ref2 = React.useRef();
const [dump, setDump] = React.useState("");
React.useLayoutEffect(() => {
const el1 = ref1.current;
const el2 = ref2.current;
if(!(el1 && el2)) return;
setDump(
`${JSON.stringify(el1.getBoundingClientRect())}\n${JSON.stringify(el2.getBoundingClientRect())}`
);
});
return (
<React.Fragment>
{dump}
<div
className="popBox"
ref={ref1}
style={{
top: "100px",
left: "100px",
width: "500px",
height: "500px",
}}
>
<div
className="popBox2"
ref={ref2}
style={{
top: "150px",
left: "150px",
width: "200px",
height: "200px",
}}
></div>
</div>
</React.Fragment>
);
}
ReactDOM.render(<BaseObject />, document.getElementById("root"));
.popBox {
background-color: #4F8989;
position: sticky;
}
.popBox2 {
background-color: #89694f;
position: sticky;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
<div id="root" />
Related
Given that we have a tag as such :
<video style={{ background: "blue", width: "111px", height: "111px" }} />
It is easy to manipulate one element such as width like this :
<video style={{ background: "blue", width: state ? '100px' : '200px', height: "111px" }} />
However if I want to change both of them upon changing the state I have to copy it over as such :
<video style={{ background: "blue", width: state ? '100px' : '200px', height: state ? '100px' : '200px' }} />
And I suspect this is not the way to go.
How to change multiple style elements without repeating myself over and over again?
Are you using CSS directly?
If you're, consider doing something like this with class
// CSS in a index.css file
.has-state {
height: 100px;
width: 100px;
}
.no-state {
height: 200px;
width: 200px;
}
.has-state, .no-state {
background: "blue"
}
// in the React file e.g. index.ts
import * as React from "react";
import "./index.css";
const Component = () => (
<video className={state ? "has-state" : "no-state"} />
)
Put the logic above the jsx:
const stateStyles = state
? {
width: '100px',
height: '100px',
border: '2px solid black'
}
: {
width: '200px',
height: '200px'
};
return (
<video style={{ background: "blue", ...stateStyles }} />
)
Im stuck on a simple error, but just can't find it.
I have created an const, too style an element. Now I want to put the constant into the CSS, but somehow that doesn't work.
I want delete this line:
<div style={OVERLAY_STYLES}/>
Can somebody explain my mistake?
const OVERLAY_STYLES = {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0,0,0, .7)",
zIndex: 1000,
};
export default function Modal({ open, children, onClick }) {
const [check, setCheck] = useState([]);
......
return ReactDOM.createPortal(
<div className="OVERLAY_STYLES">
<div style={OVERLAY_STYLES}/>
<div className="MODAL_STYLES">
<h1>Blabla.</h1>
{attribute.map((att, index) => {
return (
<div>
......
</div>
);
})}
<div className="b01">
<button onClick={() => onClick(check)} >Submit</button>
</div>
</div>
</div>
,
document.getElementById("portal")
);
}
.OVERLAY_STYLES {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0, .7);
z-index: 1000;
};
In react inline styling, all values need to be inside ' ' . Change your OVERLAY_STYLES code to:
.OVERLAY_STYLES {
position: 'fixed';
top: '0';
left: '0';
right: '0';
bottom: '0';
backgroundColor: 'rgba(0,0,0, .7)';
z-index: '1000';
};
also, no dashes so change background-color to backgroundColor
Root Cause:-
You are wrapping your <div style={OVERLAY_STYLES}/> under <div className="OVERLAY_STYLES">.
You are using the same style on both div tags which have z-index applied with the same value. So in your case:- with inline-style is appearing above the parent div by hiding it under itself.
I am attaching the snippet have a look for the reference:-
const OVERLAY_STYLES = {
position: "fixed",
top: 20,
left: 20,
right: 20,
bottom: 20,
backgroundColor: "red",
zIndex: 1000,
color:"white",
width:"50%",
};
const App = () => /*#__PURE__*/React.createElement("div", {
className: "OVERLAY_STYLES"
}, /*#__PURE__*/React.createElement("div", {
style: OVERLAY_STYLES
}, "hELLO"));
ReactDOM.render( /*#__PURE__*/React.createElement(App, null), document.getElementById("app"));
.OVERLAY_STYLES{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: ;
background-color: yellow;
z-index: 1000;
color:green;
width:100vw;
height:700px;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Solution:-
Try changing z-index/width.
Note:-Element with higher z-index will be at the top.
I have nested div elements. Outside there should be events to move and to click. I want to enable a nested element to act as a button and to prevent the event from outside to act. In the example when we click on the red part, both events are happening. How can I stop the event from the green part when we click on the red part? stopPropagation() did not do the job. I am using React and my structure is more complex than in the example. But I wanted to reduce for reasons of clarity.
I would be happy if someone can help.
#bigCircle {
display: flex;
justify-content: center;
align-items: center;
width: 180px;
height: 180px;
border-radius: 50%;
background-color: green;
}
#smallCircle {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="bigCircle">
<div id="smallCircle"></div>
</div>
<script>
document.getElementById("bigCircle").addEventListener("click",myBigCircle);
document.getElementById("smallCircle").addEventListener("click",mySmallCircle);
function myBigCircle(){
console.log("Hello");}
function mySmallCircle(){
console.log("Bye");}
</script>
</body>
</html>
I think it is related to React Hooks. Here you see the example with stopPropagation not working:
import React, { useState } from 'react';
function Test() {
let [test, setTest] = useState(false);
return (
<div id="wrapper"
style={styleBigCircle}
onMouseUp={() => {
setTest(false);
console.log("Hello", test)
}
}>
<div id="center"
style={styleSmallCircle}
onClick={(e) => {
e.stopPropagation();
setTest(!test);
console.log("Bye", test)
}}
>
</div>
</div>
);
}
const styleBigCircle = {
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "180px",
height: "180px",
borderRadius: "50%",
backgroundColor: "green"
}
const styleSmallCircle = {
width: "40px",
height: "40px",
borderRadius: "50%",
backgroundColor: "red"
}
export default Test;
I would be happy if someone knows how to fix this.
You are dealing with different events, so to prevent the child element from trigger the parent you would need to add the same event and stopPropagation() on that one instead:
<div
id="center"
style={styleSmallCircle}
onMouseUp={e => {
e.stopPropagation();
}}
onClick={e => {
setTest(!test);
console.log("Bye");
}}
/>
Here is a fully working example:
const Test = () => {
let [test, setTest] = React.useState(false);
return (
<div
id="wrapper"
style={styleBigCircle}
onMouseUp={() => {
console.log("Hello");
}}
>
<div
id="center"
style={styleSmallCircle}
onMouseUp={e => {
e.stopPropagation();
}}
onClick={e => {
console.log("Bye");
}}
/>
</div>
);
};
const styleBigCircle = {
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "180px",
height: "180px",
borderRadius: "50%",
backgroundColor: "green"
};
const styleSmallCircle = {
width: "40px",
height: "40px",
borderRadius: "50%",
backgroundColor: "red"
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Test />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Use event.stopPropagation() to prevent parent trigger.
#bigCircle {
display: flex;
justify-content: center;
align-items: center;
width: 180px;
height: 180px;
border-radius: 50%;
background-color: green;
}
#smallCircle {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="bigCircle">
<div id="smallCircle"></div>
</div>
<script>
document.getElementById("bigCircle").addEventListener("click",myBigCircle);
document.getElementById("smallCircle").addEventListener("click",mySmallCircle);
function myBigCircle(){
console.log("Hello");}
function mySmallCircle(event){
event.stopPropagation()
console.log("Bye");
}
</script>
</body>
</html>
I have a div specified like this:
<button
style={{
padding: "0px",
background: "yellow",
position: "absolute",
left: `${seat.x}%`,
top: `${seat.y}%`,
width: `${squareSizePercentageX}%`,
paddingTop: `${squareSizePercentageX}%`
}}
key={index}
/>
seat.x and seat.y is always under 100. In spite of that div get outside of parent div.
This is how parent looks like:
<div
style={{
display: "flex",
maxWidth: `calc(calc(100vmin * ${aspectRatio})+200px)`
}}
>
<div style={{ width: `calc(100vmin * ${aspectRatio})` }}>
<div
style={{ paddingTop: `${100 / aspectRatio}%`, background: "pink" }} // <-- this is here the parent
>{listContent2}</div>
</div>
<div style={{ width: "200px", background: "yellow" }}>
</div>
</div>
Here all the code:
import React from "react";
import UPUjpestRendezvenyterLayout from "../assets/UPUjpestRendezvenyterLayout.json";
class SelectSeat extends React.Component {
render() {
const seats = UPUjpestRendezvenyterLayout.seats;
const squareSizePercentageX =
UPUjpestRendezvenyterLayout.squareSizePercentageX;
const aspectRatio = UPUjpestRendezvenyterLayout.aspectRatio;
let listContent2 = seats.map((seat, index) => {
return (
<button
style={{
padding: "0px",
background: "yellow",
position: "absolute",
left: `${seat.x}%`,
top: `${seat.y}%`,
width: `${squareSizePercentageX}%`,
paddingTop: `${squareSizePercentageX}%`
}}
key={index}
/>
);
});
return (
<div
style={{
display: "flex",
maxWidth: `calc(calc(100vmin * ${aspectRatio})+200px)`
}}
>
<div style={{ width: `calc(100vmin * ${aspectRatio})` }}>
<div
style={{ paddingTop: `${100 / aspectRatio}%`, background: "pink" }} // <-- this is here the parent
>{listContent2}</div>
</div>
<div style={{ width: "200px", background: "yellow" }}>
</div>
</div>
);
}
}
export default SelectSeat;
Here an image. Small yellow rectangle should be all inside pink area.
you need to set position: relative to parent div
try by giving Css flex-wrap: wrap; and position : relative and don't forget to set left and top to your parent div , these changes can fix your problem
I want to use particles.js for my project background. I'm having an issue with height. It's not expanding height in device web. Actually height property is not working. Please help me with this.
Here is the code:
https://codesandbox.io/s/4zv0329nn0
particle.js component.
import React from "react";
import Particles from "react-particles-js";
export default () => (
<div
style={{
width: "100%",
height: "100%",
backgroundColor: "blue"
}}
>
<Particles
params={{
particles: {
number: {
value: 50
},
size: {
value: 3
}
},
interactivity: {
events: {
onhover: {
enable: true,
mode: "repulse"
}
}
}
}}
/>
</div>
);
App component.
const App = () => {
return (
<div
style={{
width: "100%",
height: "100%",
margin: "0",
padding: "0"
}}
>
<ParticleComponent />
<div
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%"
}}
>
<h1>test</h1>
</div>
</div>
);
}
Add height={window.outerHeight} prop to ParticleComponent.
Solution here 👇