I’m having trouble aligning two components within another div in React. I’m using relative positioning for the parent div (snippetButtonHolder) and absolute positioning for its children (snippet and button). I want snippet to be centered in the parent and button to be under snippet and to the right, but for some reason when I use these attributes they are positioned relative to the entire page, not to the parent div. Does anyone have a suggestion as to what I should do differently?
const styles = {
module: {
marginTop: '30px',
padding: '20px',
},
snippet: {
backgroundColor: '#f2f2f2',
border: 'solid 1px #ccc',
borderRadius: '4px',
margin: '0 auto',
padding: '10px',
width: '100%',
position: 'absolute',
left: '50%',
},
snippetButtonHolder: {
width: '95%',
position: 'relative',
},
button: {
float: 'right',
marginTop: '5px',
position: 'absolute',
left: '94%',
},
};
export default class CodeSnippet extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div style={styles.module}>
<div style={styles.snippetButtonHolder}>
<div style={styles.snippet}>
<div
{'text will go here'}
</div>
{this.state.showButton ?
<button
style={styles.button}>
Press me
</button>
: null}
</div>
</div>
</div>
);
}
}
Give this a try:
const styles = {
module: {
marginTop: '30px',
padding: '20px',
},
snippet: {
backgroundColor: '#f2f2f2',
border: 'solid 1px #ccc',
borderRadius: '4px',
display: 'inline-block',
overflow: 'hidden',
padding: '10px',
},
snippetButtonHolder: {
textAlign: 'center',
width: '95%',
},
button: {
float: 'right',
marginTop: '5px',
},
};
Related
I need to build horizontal progress bar with circle at the end in react js, as shown in picture. I am able to build progress bar with custom "%", now I want to add circle at the end with some text inside.
code for progress bar with custom "%":
codesandbox
Change progress bar component to:
<div style={containerStyles}>
<div style={fillerStyles}>
<div style={circleStyles}>{circleText}</div>
</div>
</div>
And add this styles to the component:
const circleStyles = {
display: "flex",
position: "absolute",
right: "0",
width: "50px",
height: "50px",
background: "blue",
top: "-60%",
borderRadius: "50px",
justifyContent: "center",
alignItems: "center",
color: "white"
};
And here's the App.js:
export default function App() {
return (
<div className="App">
<ProgressBar
bgcolor={item.bgcolor}
completed={item.completed}
circleText={"100%"}
/>
</div>
);
}
add a span under container div and put this style to it
<div style={containerStyles}>
<div style={fillerStyles}></div>
<span style={circleStyle}>{text}</span>
</div>
style
const circleStyle = {
height: 40,
width: 40,
position: "absolute",
right: 0,
backgroundColor: bgcolor,
borderRadius: "50%",
top: -10,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "white"
};
and then put this to containerStyle
position: "relative",
I'm working on a react. The code below is an example. ArrayExample is mapped and returned to the div component. Whenever I click the mapped div component, I want to change the value of the top of div (position: 'absolute') and place it on the right side according to the mapped div topBorder. Is there a way? I want to move it smoothly like an animation.
import React from "react";
const sample = () => {
const arrayExample = ["AAAA", "BBBB", "CCCC"];
return (
<div
style={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "500px",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f3f3f3",
}}
>
{arrayExample.map((v, i) => {
return (
<div
style={{
width: "50%",
padding: 50,
border: "1px solid black",
marginTop: 15,
}}
onClick={() => {
console.log("Event!")
}}
>
{v}
</div>
);
})}
<div style={{position: 'absolute', top: 70, right: '22%', backgroundColor: "#4285F4", width: 50, height: 150, borderRadius: 5}}>
moving screen(I want to Change top value)
</div>
</div>
);
};
export default sample;
On click of the item div, you need to figure out the distance of that div from the top, and then change the top css property of your right div according to that. To find this distance you can use offsetTop property. For animation you can use transition property. Here is the code:
import React, { useRef } from "react";
const Sample = () => {
const arrayExample = ["AAAA", "BBBB", "CCCC"];
const rightDiv = useRef();
const itemClickHandler = (i) => {
const newTopHeight = document.getElementById("container").children[i].offsetTop;
rightDiv.current.style.top = newTopHeight + 'px';
}
return (
<div
id="container"
style={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "500px",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#f3f3f3",
}}
>
{arrayExample.map((v, i) => {
return (
<div
key={i}
style={{
width: "50%",
padding: 50,
border: "1px solid black",
marginTop: 15,
}}
onClick={() => itemClickHandler(i)}
>
{v}
</div>
);
})}
<div
ref={rightDiv}
style={{
position: 'absolute',
top: 70,
right: '22%',
backgroundColor: "#4285F4",
width: 50,
height: 150,
borderRadius: 5,
transition: "top 0.5s ease-in-out"
}}>
moving screen(I want to Change top value)
</div>
</div>
);
};
export default Sample;
You can see this in action here: https://codesandbox.io/s/thirsty-curie-7mskj
In your click handler you can get the current position of the clicked div in px, you can easily google how to do this this (relative to the page, not the viewport). I would suggest storing this value in state, call it something like activeItemOffsetTop, then just set top to the current state
I am struggling to get the material-ui app bar example to work as I would like to. Codesandbox (from Material-UI website).
What I Am Trying To Achieve:
What I am trying to achieve is to get the search field to grow all the way to the right (effectively taking the majority of the app bar no matter what screen size).
What I Have Tried:
I have tried using flexGrow: 1 as follows which only grows the search bar slightly (not till the end):
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
flexGrow:1
},}
I have also tried setting width: '100%' instead of 'width: auto' but that makes the Material-UI logo disappear.
Image of desired result:
Remove the width: 'auto' from your current code,
Add minWidth with title
title: {
display: 'none',
minWidth: '120px', // Add
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%', // Keep
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
// width: 'auto', // Remove
},
},
I'm using material-ui's JSS implementation to styling classes.
I have a lot of duplicated code when it comes to the components' styles since I have separated my components.
For example, I have cards which all use common styling:
const styles = theme => ({
cardContainer: {
position: 'relative',
width: '50%',
padding: theme.spacing.unit / 2,
},
cardOuter: {
height: '100%',
width: '100%',
textAlign: 'start',
},
card: {
width: '100%',
background: theme.palette.backgrounds.card.off,
},
cardOn: {
background: theme.palette.backgrounds.card.on,
},
cardUnavailable: {
background: theme.palette.backgrounds.card.disabled,
},
cardContent: {
display: 'flex',
flexWrap: 'wrap',
minHeight: 98,
height: 98,
[theme.breakpoints.down('sm')]: {
minHeight: 74,
height: 74,
},
padding: `${theme.spacing.unit * 1.5}px !important`,
},
});
which I would only rarely want to extend upon the styles inside the component, but would like to import these objects into an existing styles function so I do not have to duplicate these objects.
Has anyone or does anyone know how to do this?
Thanks
Figured it out. For future viewers:
const styles = theme => ({
...card(theme),
grid: {
height: '100%',
width: 'fit-content',
paddingLeft: theme.spacing.unit * 2,
paddingRight: theme.spacing.unit * 2,
flexWrap: 'nowrap',
overflowY: 'hidden',
},
name: {
overflow: 'hidden',
textOverflow: 'ellipsis',
fontSize: '1.12rem',
fontColor: theme.palette.text.main,
[theme.breakpoints.down('sm')]: {
fontSize: '0.9rem',
}
},
state: {
textOverflow: 'ellipsis',
margin: '0 auto',
marginTop: theme.spacing.unit / 2,
fontSize: '1.0rem',
fontColor: theme.palette.text.light,
[theme.breakpoints.down('sm')]: {
fontSize: '0.8rem',
}
},
alarmArmedHome: {
background: theme.palette.backgrounds.card.alarm.home,
},
alarmArmedAway: {
background: theme.palette.backgrounds.card.alarm.away,
},
alarmTriggered: {
background: theme.palette.backgrounds.card.alarm.triggered,
},
icon: {
margin: '0 auto',
color: theme.palette.text.icon,
fontSize: '2.7rem',
[theme.breakpoints.down('sm')]: {
fontSize: '1.7rem',
}
},
});
card.js
const styles = (theme) => ({
cardContainer: {
position: 'relative',
width: '50%',
padding: theme.spacing.unit / 2,
},
cardOuter: {
height: '100%',
width: '100%',
textAlign: 'start',
},
card: {
width: '100%',
background: theme.palette.backgrounds.card.off,
},
cardOn: {
background: theme.palette.backgrounds.card.on,
},
cardUnavailable: {
background: theme.palette.backgrounds.card.disabled,
},
cardContent: {
display: 'flex',
flexWrap: 'wrap',
minHeight: 98,
height: 98,
[theme.breakpoints.down('sm')]: {
minHeight: 74,
height: 74,
},
padding: `${theme.spacing.unit * 1.5}px !important`,
},
});
export default styles;
So you pretty much have to join the objects passing in the theme if required:
...card(theme),
I am trying to create custom header in React.js. I have a working prototype in this JSFiddle.
The problem is, React does not go well with css pseudo-elements, so following this advice I tried to "translate" it into React component:
var lineAfterStyle = {
position: 'absolute',
top: '51%',
overflow: 'hidden',
width: '50%',
height: '1px',
content: '\a0',
backgroundColor: 'red'
};
var lineBeforeStyle = {
position: 'absolute',
top: '51%',
overflow: 'hidden',
width: '50%',
height: '1px',
content: '\a0',
backgroundColor: 'red',
marginLeft: '-50%',
textAlign: 'right',
};
......
<div>
<div style={lineBeforeStyle} />
<h1 style={headerStyle}>Hello World!</h1>
<div style={lineAfterStyle} />
</div>
This does not work as expected--horizontal lines are placed somewhere on the screen and they are NOT inlined with the header. Is there any way to make it better?