Why padding never works in React Native? I have 10px padding in the image and the text box below:
const styles = StyleSheet.create({
container: {
marginTop: 75,
alignItems: 'center'
},
image: {
width: 107,
height: 165,
padding: 10,
backgroundColor:'blue'
},
description: {
padding: 20,
margin: 10,
fontSize: 15,
color: '#656565',
backgroundColor:'red'
}
});
Result:
Any ideas why? Did I miss something?
Use this for padding:
function padding(a, b, c, d) {
return {
paddingTop: a,
paddingRight: b ? b : a,
paddingBottom: c ? c : a,
paddingLeft: d ? d : (b ? b : a)
}
}
In practice
<Text style={{...padding(10, 20, 10, 5), color: "black"}}>Some text</Text>
Android with React Native tends to not like padding, unless it has a border. A temporary fix would be to change all of your "paddingXXX" to "marginXXX" to get the approximate styling you want.
const styles = StyleSheet.create({
container: {
marginTop: 75,
alignItems: 'center'
},
image: {
width: 107,
height: 165,
margin: 10,
backgroundColor:'blue'
},
description: {
margin: 30,
fontSize: 15,
color: '#656565',
backgroundColor:'red'
}
});
It's a really bad workaround, but I have yet to see a concise fix to it. As far as I know, there is an issue on the Git repo but hasn't been fixed yet.
padding issue for android is fixed in react-native v0.31.0 version.
for more details you can go to react-natvie release changelog https://github.com/facebook/react-native/releases
Another factor to consider is flexbox being used everywhere. Flexbox can take away bottom padding from what I have found, so wrapping in another View might be necessary.
referring to https://stackoverflow.com/a/55724273/12962610 answer
improved version:
export const padding = (a, b, c, d) => ({
paddingTop: a,
paddingRight: b ?? a,
paddingBottom: c ?? a,
paddingLeft: d ?? b ?? a,
})
Padding in react native only accepts a number and not any other character.
Eg:
<TextInput placeholder="Enter Text" style={{padding: 30}} />
Similar to https://stackoverflow.com/a/55724273, but can be done in a more concise manner with default arguments.
/**
* Padding utility function that mimics padding syntax in web
* https://developer.mozilla.org/en-US/docs/Web/CSS/padding
*/
export function padding(
top: number | string | null,
right: number | string | null = top,
bottom: number | string | null = top,
left: number | string | null = right
) {
return {
paddingTop: top ?? undefined,
paddingRight: right ?? undefined,
paddingBottom: bottom ?? undefined,
paddingLeft: left ?? undefined,
};
}
<Text>
{` ${description} `}
</Text>
Adding space before and after like above helped me in most cases. Very helpful when you have nested 'Text' tags.
Use this for padding:
<View style={styles.textPadding}>
<Text>balablabla</Text>
</View>
textPadding: {
color: '#fff',
fontSize: 25,
fontWeight: 'bold',
backgroundColor: "#FFA679",
paddingVertical: 20,
paddingHorizontal: 20,
textAlign: "center"
},
If You are having issues and using margin is not an option, consider replacing View with Button or some other component that fixes the problem for You.
I am using ReactXP and for some reason, using Styles.createButtonStyle with ReactXp's Button worked, and Styles.createViewStyle with View did not.
Padding in react native only accepts a number and not any other character.
Eg:
<TextInput placeholder="Enter Text" style={{padding: 30}} />
I have solution for your problem. Try this:
<Text>
<View style={{padding: 20, backgroundColor: 'red'}}>
<Text style={{color: 'white'}}>Description</Text>
</View>
</Text>
Related
I am currently attempting to create a bar that fills in based on arrays of numbers that are fed to it out of 1440 (for minutes in a day). For instance, if [3, 400] was inputted, the view would fill in the area corresponding to 3-400 minutes with some color.
I'm not sure where to start here, since the only idea I have had is to fill the parent view with 1440 other views which I can then fill based on the input, which certainly would not be a great idea. Any help would be much appreciated.
I think I figured it out. This was my solution:
import React from 'react'
import { StyleSheet, View, Text } from 'react-native'
export default function TimeAvailabilityIndicator() {
const testArray = [[130, 210], [1000, 1300], [500, 800]]
const minuteToPercentageConverter = (minute) => {
return (minute * 100) / 1440
}
return (
<View style={styles.parentView}>
{testArray.map(time => {
return <View
style={{
position: 'absolute',
left: minuteToPercentageConverter(time[0]) + '%',
right: (100 - minuteToPercentageConverter(time[1])) + '%',
height: 16,
backgroundColor: 'red'
}}
/>
})}
</View>
)
}
const styles = StyleSheet.create({
parentView: {
borderColor: 'black',
borderWidth: 2,
height: 20,
marginTop: 10,
position: 'relative'
}
})
I'm currently trying to dynamically display different rows of buttons that are evenly spaced out from each other. In my code, two rows have five buttons each, and the third row has only two buttons. Since both buttons are being created using the same component, I was wondering if there was any CSS to help me do this properly.
Currently, here is the code for my the button component:
const NodesOptionButton = (props) => {
const styles = StyleSheet.create({
bold: {
fontWeight: '800',
},
textWrapper: {
width: 60,
height: 60,
borderWidth: 1,
borderStyle: 'solid',
borderColor: '#000',
padding: 12,
marginVertical: 8,
backgroundColor: props.isActive ? '#000' : '#fff',
alignItems: 'center',
justifyContent: 'center',
},
activeTextColor: {
color: '#fff',
}
});
And I'm rendering the three rows of button through this code:
const NPage = (props) => {
const styles = StyleSheet.create({
nodeOptionsContainer: {
flexDirection:'row',
backgroundColor:'red',
display: 'flex',
justifyContent: 'space-evenly',
},
});
//lots of code with logic
return (
<React.Fragment>
<View style={styles.nodeOptionsContainer}>
{nodeNumberOptions}
</View>
<View style={styles.nodeOptionsContainer}>
{clincallyOccultOptions}
</View>
<View style={styles.nodeOptionsContainer}>
{MSIOptions}
</View>
</React.Fragment>
)
Is there any suggestions, or would I have to create a new component for that specific button? Thanks!
You want the two last buttons to take up the whole row? You can always try to add:
flex-grow: 1
to your button component.
If you want your buttons to always take up the whole row, you should just need to add flex: 1 to your Button component root View, and you don't need space-evenly in the parent.
If that's not the case, maybe you should post a pic of the desired design and the current design with problem. It helps understand.
p.s: another tip for performance...define your style outside your component.
I have the following set of style rules:
status_in_progress: {
fontSize: 14,
backgroundColor: theme.palette.success.dark,
padding: 2,
paddingLeft: 5,
paddingRight: 5,
display: "inline-block",
},
status_complete: {
fontSize: 14,
backgroundColor: theme.palette.primary.dark,
padding: 2,
paddingLeft: 5,
paddingRight: 5,
display: "inline-block",
},
status_overdue: {
fontSize: 14,
backgroundColor: theme.palette.error.dark,
padding: 2,
paddingLeft: 5,
paddingRight: 5,
display: "inline-block",
},
As you can see, much of this is identical. I'd love to be able to define a set of rules like this:
status: {
fontSize: 14,
padding: 2,
paddingLeft: 5,
paddingRight: 5,
display: "inline-block",
in_progress: {
backgroundColor: theme.palette.success.dark,
},
complete: {
backgroundColor: theme.palette.primary.dark,
},
...
},
But it seems like MUI does not like that. What's the most efficient way to factor out the common rules?
I am also using ReactJS.
When we write CSS styles inside a JS object, the keys of the object get parsed to find the corresponding CSS property. For example, inside your status object, the key fontSize is parsed into font-size, which is a valid CSS property.
However, in your refactored code, you have included keys of in_progress and complete, which do not correspond to any valid CSS properties. Therefore, the parser has trouble understanding what you are trying to achieve with these keys.
You can try the following refactoring:
import React from "react";
import clsx from "clsx";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
status: {
fontSize: 14,
padding: 2,
paddingLeft: 5,
paddingRight: 5,
display: "inline-block",
},
in_progress: {
backgroundColor: theme.palette.success.dark,
},
complete: {
backgroundColor: theme.palette.primary.dark,
},
overdue: {
backgroundColor: theme.palette.error.dark,
}
});
function ExampleComponent(props) {
const classes = useStyles(props);
return (
<div>
<p className={clsx(classes.status, classes.in_progress)}>Sample Text</p>
</div>
)
}
I moved the in_progress, complete and overdue keys outside the status object.
In my sample code, I added two classes of classes.status and classes.in_progress to an element. This is equivalent of adding classes.status_in_progress before you re-factor your code:
<p className={clsx(classes.status, classes.in_progress)}>Sample Text</p>
Note that clsx() is a tiny utility that is pre-installed in your project that allows you to construct className strings easier. The repo of clsx lists more examples on how you can use it. If you don't want to use clsx(), the following code works the same:
<p className={`${classes.status} ${classes.in_progress}`}>Sample Text</p>
I prefer clsx() because the template string syntax can get tedious sometimes. If you want to use clsx(), remember to import it by adding import clsx from "clsx"; at the top of the file.
I have an element has these CSS properties, applied with Stylesheet option of react-native
const styles = StyleSheet.create({
card: {
marginTop: 30,
marginLeft: 50,
marginRight: 50,
padding: 20,
backgroundColor: '#74C8AF',
borderRadius: 10,
flex: 1,
flexDirection: 'column',
},
})
I want to implement this "card" property to all my cards but just want to alter only backgroundColor property unique to each card. Is there any way to handle this just in one card object, without setting different card objects for each individual?
I tried to change style like this but it discards whole object and only applies backgroundcolor
<Card style={styles.card, {backgroundColor:"#9932cc"}}>
//...
</Card>
use like this
<Card style={[styles.card, {backgroundColor:"#9932cc"}]}>
instead of
<Card style={styles.card, {backgroundColor:"#9932cc"}}>
I usually do something along the lines of:
<View style={this.jewelStyle()} />
jewelStyle = function(options) {
return {
borderRadius: 12,
background: randomColor(),
}
}
Every time View is rendered, a new style object will be instantiated with a random color associated with it. Of course, this means that the colors will change every time the component is re-rendered, which is perhaps not what you want. Instead, you could do something like this:
var myColor = randomColor()
<View style={jewelStyle(myColor)} />
jewelStyle = function(myColor) {
return {
borderRadius: 10,
background: myColor,
}
}
I am trying to achieve dynamic padding top and bottom. I am aware that paddingTop and paddingBottom with % will use the width of the container and I am fine with that.
Unfortunately when I do set the paddingTop to any value with %, it sets the paddingBottom to the same value. Basically paddingTop: '5%', paddingBottom: '0%' will give me equal 5% paddings on both sides.
If I set paddingBottom to any % value - it's just being added to the value that came form the top. So: paddingTop: '5%', paddingBottom: '10%' results in paddingBottom equal to 15%...
I checked the same solution in a web project and there it works as expected.
The snack presenting the problem:
https://snack.expo.io/BJ9-2t8LB
The problem is on both Android and iOS.
How to solve it?
Apply the value to the child container to be applied, not to the parent container.
I have modified the answer according to the conditions you want. You should send Bottom's territory to the parent's container. Because they interact with each other in their child's container, they must be independent.
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.wrapper}>
<View style={styles.inner}>
<View style={{ backgroundColor: 'yellow' }}>
<Text>TOP</Text>
</View>
</View>
<View style={{ backgroundColor: 'red', }}><Text>BOTTOM</Text></View>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex:1,
paddingLeft: 24,
paddingRight: 24,
backgroundColor: 'green',
paddingBottom:"5%"
},
inner: {
flex:1,
justifyContent: 'space-between',
backgroundColor: 'blue',
marginTop:"10%"
},
});
That is strange behavior, you should bring it up as an issue to react-native.
In the meantime, a workaround would be applying marginTop and marginBottom to the inner View, instead of paddingTop and paddingBottom to the wrapper View.
const styles = StyleSheet.create({
ayz:{
marginTop:"15%",
backgroundColor:'pink',
alignItems:'center',
justifyContent:'center',
},
asd:{
color:'white',
fontSize:50,
fontWeight:'bold'
}
});