I have a child div that is slightly larger than the parent:
When I change the width of the child to 100% it doesn't centre:
what I want is that it will be the same size as parent, and centred and have the side borders of the Tax column still aligned with the table borders:
css for the parent:
const HeaderRowContainer = styled.div(({ theme }) => ({
height: '32px',
backgroundColor: theme.alabaster,
padding: '0',
lineHeight: 1.2
}))
child:
const Container = styled.div(({ gutterSpacing, justifyContentEnd, alignItems, flexWrap }) => ({
width: '100%',
height: '100%',
display: 'flex',
alignItems: alignItems || 'flex-start',
boxSizing: 'border-box',
flexDirection: 'row',
flexWrap: flexWrap || 'wrap',
flex: '0 1 auto',
justifyContent: justifyContentEnd ? 'flex-end' : 'flex-start',
marginLeft: `-${gutterSpacing}px`,
marginRight: `-${gutterSpacing}px`
}))
Related
I have some react-native code, where I have a pop-up modal. I created it using flex, but for some reason the text will not vertically align. I solved it using top = 30%, but then my touchable opacities(surrounding the texts) do not span all of the free space available. And I feel this is a hacky solution.
Curious if there is a better one, to automatically align the text vertically and make sure the touchable opacities take up the free space available to them?
Below is my code:
<Modal
isVisible={confirmationVisible}
onBackdropPress={() => toggleConfirmation()}
style={styles.confirmationModal}
>
<Text style={styles.confirmationTitle}>Would you like to add a beacon to {assetName}?</Text>
<TouchableOpacity style={styles.confirmationContainer} onPress={() => navigateAway("AddAssetScreenFinish")}>
<Text style={styles.confirmationText}>No, I'm done</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.confirmationContainer} onPress={() => navigateAway("AddBeaconExistingScreen")}>
<Text style={styles.confirmationText}>Yes, an existing Beacon</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.confirmationContainer} onPress={() => navigateAway("AddBeaconScreen")}>
<Text style={styles.confirmationText}>Yes, a new Beacon</Text>
</TouchableOpacity>
</Modal>
Below is my styling:
confirmationModal: {
flex: 0.3,
width: "60%",
alignItems: "center",
justifyContent: "space-evenly",
backgroundColor: "white",
marginTop: "auto",
marginBottom: "auto",
marginLeft: "auto",
marginRight: "auto",
borderRadius: 8
},
confirmationTitle: {
fontWeight: "bold",
textAlign: "center",
margin: 5,
paddingLeft: 20,
paddingRight: 20
},
confirmationContainer: {
borderTopColor: "lightgrey",
borderTopWidth: 1,
width: "100%"
},
confirmationText: {
textAlign: "center",
color: COLORS.purple
},
Edit:
using this modal if curious
Also, have tried justifyContent on confirmationContainer but it does not work, unsure why
Edit2:
Got the solution. Seems flex is scaling the height and width had to be set manually for my text element. Removing the justifyContent and alignItems from a parent container, I was able to use textAlignVertical for my title and scale titleContainer vs touchableContainers with flex 2 and flex 1 respectively. Not sure what is going on, but the touchable now scales the whole free space and the text is aligned vertically...used AnthonyDev220's solution and reworked it so marked him as best answer, updated styles jsx did not change:
confirmationModal: {
flex: 0.3,
width: "60%",
backgroundColor: "white",
marginTop: "auto",
marginBottom: "auto",
marginLeft: "auto",
marginRight: "auto",
borderRadius: 8
},
confirmationTitle: {
fontWeight: "bold",
textAlign: "center",
textAlignVertical: "center",
flex: 2,
paddingLeft: 20,
paddingRight: 20
},
confirmationContainer: {
borderTopColor: "lightgrey",
borderTopWidth: 1,
flex: 1,
width: "100%"
},
confirmationText: {
marginTop: "auto",
marginBottom: "auto",
textAlign: "center",
color: COLORS.purple
},
You could try adding textAlignVertical: "center" to your confirmationText
or
Try wrapping your component inside a component and then style your componenet.
<TouchableOpacity style={styles.confirmationContainer} onPress={() => navigateAway("AddAssetScreenFinish")}>
<View style={{flex:1,justifyContent: "center",alignItems: "center"}}>
<Text style={styles.confirmationText}>No, I'm done</Text>
</TouchableOpacity>
</View>
same for your other two <Text> components.
confirmationContainer: {
display: flex,
justifyContent: center,
alignItems:center,
borderTopColor: "lightgrey",
borderTopWidth: 1,
width: "100%"
}
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'm trying to position the FullWidthDiv component to span from the beginning of the MainDiv side, all the way to the end. I've tried giving in an absolute position and playing around with flex, but I can't get it to not start from the SubDiv component.
Is it possible to achieve this?
My CodeSandbox approach.
Here is what I'm trying to achieve
It is a little bit hacky, but you can center ChildDiv with align-items: center.
Also, shrink the FullWidthDiv to 280.
And last you have to add flex: 1, width: 100% to the div, that hold SubChildDiv inside App component.
export default function App() {
return (
<MainDiv>
<ChildDiv>
<div style={{flex: 1, width: '100%'}}>
<SubChildDiv />
<SubChildDiv />
</div>
<FullWidthDiv />
</ChildDiv>
</MainDiv>
);
}
const MainDiv = ({ children }) => (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: 250,
height: 250,
backgroundColor: "red",
padding: "1rem"
}}
>
{children}
</div>
);
const ChildDiv = ({ children }) => (
<div
style={{
width: 200,
height: 200,
backgroundColor: "blue",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "space-between"
}}
>
{children}
</div>
);
const SubChildDiv = () => (
<div
style={{
display: "flex",
width: "100%",
height: 30,
backgroundColor: "green",
border: "1px solid black"
}}
/>
);
const FullWidthDiv = () => (
<div
style={{
width: 280,
height: 30,
border: "1px solid black",
backgroundColor: "green"
}}
/>
);
If you want the FullWidthDiv to be with 100% width, you have to calculate the 100% width and add the padding from both sides of MainDiv it will look something like that: calc(100% + 2rem).
I have a screen where I want to place the first, main text item (Filter)in the exact middle of the screen while the second item (All Delete) should be at the right end. Both of them should be in the same line.
I would prefer not to use padding/margins since they can vary in different phone sizes. I am already using text-align but it doesn't work for me.
export default function App() {
return (
<View style={styles.container}>
<View style={styles.topTextContainer}>
<Text style={styles.filterText}>Filter</Text>
<Text style={styles.deleteAllText}>All Delete</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
topTextContainer: {
paddingTop: moderateScale(35),
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
filterText: {
fontSize: moderateScale(15),
fontWeight: 'bold',
textAlign: 'center'
},
deleteAllText: {
fontSize: moderateScale(13),
color: '#363636',
fontWeight: '300',
marginLeft: moderateScale(75),
},
});
Codesandbox: https://snack.expo.io/#nhammad/frowning-bagel
You can use a absolute position for the delete button and set right:0 like below.
deleteAllText: {
fontSize: moderateScale(13),
color: '#363636',
fontWeight: '300',
position: 'absolute',
right: 0
}
The other option is to use marginLeft:'auto' for the both the texts which can help but wont keep the first one in center.
With exact milld do you mean in the middle of the screen width and height like this:
const styles = StyleSheet.create({
container: {
flex: 1,
},
topTextContainer: {
paddingTop: moderateScale(35),
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
height: "100%"
},
filterText: {
fontSize: moderateScale(15),
fontWeight: 'bold',
textAlign: 'center'
},
deleteAllText: {
fontSize: moderateScale(13),
color: '#363636',
fontWeight: '300',
position: "absolute",
right: 0
//marginLeft: moderateScale(75),
},
});
If yes, you should set the height: "100%"
if you want to have it on the top middle than this should be the right approach:
const styles = StyleSheet.create({
container: {
flex: 1,
},
topTextContainer: {
paddingTop: moderateScale(35),
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
filterText: {
fontSize: moderateScale(15),
fontWeight: 'bold',
textAlign: 'center'
},
deleteAllText: {
fontSize: moderateScale(13),
color: '#363636',
fontWeight: '300',
position: "absolute",
right: 0
//marginLeft: moderateScale(75),
},
});
setting deleteAllText position: absolute and right: 0
Here is what I want:
Here is my result:
I try to assign the style to my input props, but no luck, any ideas? Thanks.
<TextField
key={'verifyKey_'+i}
multiline={false}
InputProps={{
textAlign: 'center',
disableUnderline: true,
style: {
color: 'red',
textAlign: 'center'
}
}}
style={{
height: '50px',
width: '50px',
textAlign: 'center',
justifyContent: 'center'}}/>
Using flexbox and replace textAlign: 'center' with alignItems: 'center':
{
height: '50px',
width: '50px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
Your code is essentially correct, you just need to lower case "InputProps" to "inputProps". Casing is important here.
inputProps={{ style: {textAlign: 'center'} }}
See also https://github.com/mui/material-ui/issues/5139
You are using
width: '50px'
But you had it to 100%
width: '100%'
To make textAlign property worked properly..
If above wouldn't worked then add one more style to specify more precise
display:block for your text field.