Keeping a component 50% bottom to its top component - css

I'm trying to make a profile page ui, Where the profile data like name and bio container will stay 50% to the bottom of its top component which is cover picture right now.
So this is my React Native code,
<View style={styles.container}>
<View style={styles.coverContainer}>
</View>
<View style={styles.profileDataContainer}>
</View>
<View style={styles.intrestsContainer}>
</View>
<View style={styles.topicsContainer}>
</View>
</View>
And current styles,
const styles = StyleSheet.create({
container: {
},
coverContainer: {
height : 200,
backgroundColor : 'blue'
},
profileDataContainer: {
marginHorizontal : 30,
backgroundColor: 'white',
height : 200,
shadowColor: "#e5e5e5",
shadowOffset: {
width: 0,
height: 2
},
shadowRadius: 2,
shadowOpacity: 1.0,
elevation : 4,
marginTop : -100,
}
});
I have added marginTop : -100 to make it look like the structure I want.
So this is what it looks like right now after adding marginTop to -100, But that's not responsive, When I increase the size of that white block. It doesn't stay in center anymore.
Need Help on how to do that :(

You can do it using percentage instead of logical pixels like in this example :
const WindowHeight = Dimensions.get('window').height;
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.headerBackground}/>
<View style={styles.header}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
backgroundColor: 'grey',
},
headerBackground: {
height: '30%',
width: '100%',
backgroundColor : 'blue'
},
header: {
height: '30%',
width: '80%',
marginTop: WindowHeight * -0.15,
backgroundColor : 'white'
}
});
In this example I set the height of the blue background and the white header to 30% of the window's height, and the marginTop to -15% of the window's height (I have to use Dimensions because if I use a percentage it'll be the percentage of the width...)
You can run my example on snack : https://snack.expo.io/Hyd7ChplX

You can nest your profileDataContainer in your coverContainer and place it absolute with top 50%. Hope you can convert it yourself to your React Native code...
Example:
.coverContainer{
height: 200px;
background-color: blue;
position: relative;
width: 100%;
}
.profileDataContainer {
position: absolute;
right: 10%;
left: 10%;
display: block;
top: 50%;
background-color: red;
height: 200px;
}
<div class="coverContainer"><div class="profileDataContainer"></div></div>

Related

Image 3D Hover Effect

I discovered this nice 3D Hover Image Effect - https://codepen.io/kw7oe/pen/mPeepv
With the help of tutorials and guides I know I can style a component with Materials UI and apply it this way the CSS what I do. In the example link the Image is declared as background in CSS. I did it not in CSS but with the MUI Image tag. However it does not throw errors but its not working at all and I am unsure as why.
For the information I build it in React TS.
import React from 'react';
import { Box, Typography } from '#mui/material';
import Image from 'mui-image';
const styles = {
body: {
background: '#ECECEC',
},
footer: {
width: '50%',
marginLeft: '25%',
textAlign: 'center',
fontFamily: 'Julius Sans One, sans-serif',
marginTop: '24px',
},
container: {
maxWidth: '720px',
margin: '24px auto 48px auto',
},
h1: {
fontFamily: 'Montserrat, sans-serif',
textTransform: 'uppercase',
},
h2: {
fontFamily: 'Julius Sans One, sans-serif',
fontSize: '2.5rem',
},
row: {
marginTop: '12px',
},
column: {
display: 'inlin-block',
textAlign: 'center',
},
figure: {
overflow: 'hidden',
},
'a:hover': {
textDecoration: 'none',
},
'column img': {
display: 'block',
width: '100%',
height: '300px',
},
tdimension: {
width: '300px',
height: '300px',
margin: '20px auto 40px auto',
perspective: '1000px',
},
'tdimension a ': {
display: 'block',
width: '100%',
height: '100%',
backgroundSize: 'cover',
transformStyle: 'preserve-3d',
transform: 'rotateX(70deg)',
transition: 'all 0.8s',
},
'tdimension:hover a': {
transform: 'rotateX(20deg)',
},
'tdimension a:after': {
content: '',
position: 'absolute',
left: 0,
bottom: 0,
width: '100%',
height: '40px',
background: 'linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.1))',
transform: 'rotateX(90deg)',
transformOrigin: 'bottom',
},
};
function Hover() {
return (
<Box style={styles.container}>
<Box style={styles.row}>
<Typography style={styles.h1}>Image Hover Effect</Typography> <Typography style={styles.h2}>3D Hover Effect</Typography>
</Box>
<Box style={styles.row}>
<Box style={styles.tdimension}>
<Image src="https://mir-s3-cdn-cf.behance.net/project_modules/disp/e8346826957515.56361c2106f3f.png" style={styles['tdimension a ']}/>
</Box>
</Box>
</Box>
);
}
export { Hover };
I would replace all style attributes with sx since MUI encourages the usage of sx prop and prefers it over style attribute:
https://mui.com/system/the-sx-prop/
I would also stick to the background url inside the <a/> since the 3D Hover Effect transformations are being applied to that tag.
return (
<Box sx={styles.container}>
<Box sx={styles.row}>
<Typography sx={styles.h1}>Image Hover Effect</Typography>
<Typography sx={styles.h2}>3D Hover Effect</Typography>
</Box>
<Box sx={styles.row}>
<Box sx={styles.tdimension}>
</Box>
<Divider sx={{ padding: "1px" }} />
</Box>
</Box>
);
Now inside your styles object wrap everything related to tdimension inside a nested styling object. Your <Box/> makes use of styles.tdimension and this way all your substyling won't get lost.
...
tdimension: {
width: "300px",
height: "300px",
margin: "20px auto 40px auto",
perspective: "1000px",
a: {
background:
'url("https://mir-s3-cdn-cf.behance.net/project_modules/disp/e8346826957515.56361c2106f3f.png")',
display: "block",
width: "100%",
height: "100%",
backgroundSize: "cover",
transformStyle: "preserve-3d",
transform: "rotateX(70deg)",
transition: "all 0.8s",
},
"&:hover a": {
transform: "rotateX(20deg)",
},
"a:after": {
content: '""',
position: "absolute",
left: 0,
bottom: 0,
width: "100%",
height: "40px",
background: "linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.1))",
transform: "rotateX(90deg)",
transformOrigin: "bottom",
},
},
The result should be pretty identical to the codepen now.

Width and Height In react-native

please explain by what principle view sizes with element style are formed. I learned FlexBox however it breaks all my understanding.
code
export const App = () => {
return (
<SafeAreaView>
<View style={styles.container}>
<View style={styles.element}>
<View style={styles.element1}></View>
</View>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
backgroundColor: 'green',
},
element: {
// width: '100%',
// height: '100%',
backgroundColor: 'yellow',
// top: '5%',
},
element1: {
width: '50%',
height: '80%',
backgroundColor: 'red',
},
});
You can use flex: 1 instead of
width: '100%', height: '100%',.
The Flex: 1 means the component (In case, the view) have a priority value of 1, wich means, if there'snt another component on the same view with flex: 1, the component will take the entire screen.
If, there's two components with flex: 1, each one will take 50% of the entire screen.
Here's the documentation: React native flexbox

Center Activity Indicator with absolute position in React Native

i am using View overlay and ActivityIndicator to hide loading map in the background. The solution i am using is View with absolute position to make it on top of everything and putting activityindicator on top, so there is something happening.
The issue is, that because the ActivityIndiator size cant be set to specific pixels on iOS, i dont know what is its size and thus i cant center it properly. Or i didnt figure out way to do it.
Here is some code:
<View style={styles.whiteOverlay}>
<ActivityIndicator style={styles.indicator} size="large" color={colors.color4} />
</View>
whiteOverlay: {
width: screen.height,
height: screen.height,
backgroundColor: 'white',
position: 'absolute',
zIndex: 20
},
indicator: {
zIndex: 21,
position: 'absolute',
left: screen.width/2,
top: screen.height/2
}
This positions the indicator offseted from center. I can put there some magic numbers to make it work for a specific device, guessing the size of the indicator, but it then doesnt work on other devices. Thanks for any help.
If you want to center the ActivityIndicator on the screen, you can set the style like this.
<View style={{ flex: 1, alignItems: "center", justifyContent: "center", zIndex: 20 }}>
<ActivityIndicator
size="large" color={colors.color4}
/>
</View>
orYou can use style'sposition
<View style={styles.whiteOverlay} >
<ActivityIndicator
size="large" color={colors.color4}
/>
</View >
...
whiteOverlay: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}
Couple options;
NON-Flex
whiteOverlay: {
width: screen.height,
height: screen.height,
backgroundColor: 'white',
position: 'absolute',
zIndex: 20
},
indicator: {
zIndex: 21,
position: 'absolute',
left: 50%,
top: 50%,
transform: translate(-50%, -50%)
}
WITH-Flex (assumes indicator renders as child of overlay);
whiteOverlay: {
width: screen.height,
height: screen.height,
backgroundColor: 'white',
position: 'absolute',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 20
}

MUI Card text overlay

I'm using the MUI Card and CardMedia components in my app but can't figure out how to overlay text on top of the image. This is a simplified example of what I'm trying:
<Card>
<CardMedia image={this.props.preview} style={styles.media}/>
<div style={styles.overlay}>
this text should overlay the image
</div>
</Card>
const styles = {
media: {
height: 0,
paddingTop: '56.25%' // 16:9
},
overlay: {
position: 'relative',
top: '20px',
left: '20px',
color: 'black',
backgroundColor: 'white'
}
}
I've tried placing the text div in above the CardMedia, below it, inside it, outside the Card entirely, and using different position values but can't figure this out at all. The beta versions of MUI included an overlay property on the CardMedia, but the v1 library doesn't seem to have anything like that.
Any know how to properly do this? Thanks in advance for any help!
Your CSS is off, you'll want to absolutely position the styles.overlay, and make sure the Card is position relative
Try something like this:
<Card style={styles.card}>
<CardMedia image={this.props.preview} style={styles.media}/>
<div style={styles.overlay}>
this text should overlay the image
</div>
</Card>
const styles = {
media: {
height: 0,
paddingTop: '56.25%' // 16:9
},
card: {
position: 'relative',
},
overlay: {
position: 'absolute',
top: '20px',
left: '20px',
color: 'black',
backgroundColor: 'white'
}
}
Use the code below if you want to have an overlay like the Card in version 0. Remember to set the position of the container to relative so the absolute position of the overlay can take effect:
<Card sx={{ maxWidth: 345 }}>
<Box sx={{ position: 'relative' }}>
<CardMedia
component="img"
height="200"
image="https://mui.com/static/images/cards/contemplative-reptile.jpg"
/>
<Box
sx={{
position: 'absolute',
bottom: 0,
left: 0,
width: '100%',
bgcolor: 'rgba(0, 0, 0, 0.54)',
color: 'white',
padding: '10px',
}}
>
<Typography variant="h5">Lizard</Typography>
<Typography variant="body2">Subtitle</Typography>
</Box>
</Box>
{...}
</Card>

Can't align button to the bottom left of the screen - React Native

I would like to position my button to the bottom left of the screen. I have tried using bottom: 0 and left: 0, but that did not do anything. I researched a bit and discovered that I need to set the position: 'absolute'. However, when I do this, my button disappears completely.
How can I position by the button to the bottom left of the screen?
Here is my code:
import React, { Component } from 'react';
import { Button,Alert, TouchableOpacity,Image } from 'react-native'
import {
AppRegistry,
StyleSheet,
Text,
View,
} from 'react-native';
class Project extends Component {
render() {
return (
<View style={{backgroundColor: '#375D81', flex: 1}}>
<View style = {styles.container}>
<TouchableOpacity style = {styles.buttonText} onPress={() => { Alert.alert('You tapped the button!')}}>
<Text>
Button
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
main: {
backgroundColor: 'blue'
},
container: {
alignItems: 'center',
},
buttonText: {
borderWidth: 1,
padding: 25,
borderColor: 'black',
backgroundColor: '#C4D7ED',
borderRadius: 15,
bottom: 0,
left: 0,
width: 100,
height: 100,
position: 'absolute'
}
});
AppRegistry.registerComponent('Project', () => Project);
You've forgotten to flex your container. Add: flex: 1 in there and you're all good:
container: {
alignItems: 'center',
flex: 1
},
You just need to set a width and height to your button then:
justifyContent: 'flex-end'
That's it
App.js
import React from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import styles from './styles';
class Example extends React.Component {
render() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button}>
<Text style={styles.text}>Button</Text>
</TouchableOpacity>
</View>
);
}
}
export default Example;
styles.js
export default {
container: {
flex: 1,
justifyContent: 'flex-end',
},
button: {
justifyContent: 'center',
textAlign: 'center',
width: 70,
height: 40,
backgroundColor: 'green',
borderRadius: 10,
margin: 20,
},
text: {
color: 'white',
textAlign: 'center',
margin: 10,
},
};
You will get something like this:
See Expo Snack: snack.expo.io/#abranhe/button-left
React-native elements are "rendered" from the top left when defining their position absolutely. This means when you are defining bottom: 0 and left: 0, this is rendering the item where you want horizontally, but vertically it will be off the screen. switch to
position 'absolute',
bottom: 100,
left: 0,
This should be what you are looking for

Resources