There's a couple of different ways to apply styles to a React Native component, some of which (like in web CSS) are more readable and maintainable than others.
Note that unlike in CSS, there's (almost) no inheritance in RN styles. Setting one font-family
for the whole application by setting it on the outermost <View />
doesn't work, it needs to be explicitly set for each <Text />
component.
It might seem a little annoying at first sight, but it makes RN truly modular. A component should look the same, regardless of which parent component renders it.
๐ฑ Inline Styling
To define inline-styles, directly pass an object literal:
return (
<View style={{ flex: 1, backgroundColor: '#ace' }}></View>
)
In most cases, this is going to be messy very quickly. It also recreates the style object with every render.
๐ฑ Using StyleSheet.create
This feels a bit more like writing CSS for web. It's up to you if you want to create the styles in a separate file, or if you want to keep them inside the component's file - I prefer the latter (with one exception, see next section).
import { StyleSheet, View } from 'react-native';
export default function App(){
return (
<View style={ styles.container }></View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ace'
}
})
๐ฑ Defining Global Styles
Every app has certain reoccuring style values (the most obvious example would be a colour scheme, or text formatting), so it makes sense to keep those in a separate file and import them where needed:
globalStyles.js
import { StyleSheet } from 'react-native';
export const globalStyles = StyleSheet.create({
heading: {
fontSize:30
},
paragraph: {
fontSize:18
}
})
App.js
import { StyleSheet, View, Text } from 'react-native';
import { globalStyles } from './styles/globalStyles';
export default function App(){
return (
<View style={ styles.container }>
<Text style={ globalStyles.heading }>React Native & Expo</Text>
<Text style={ globalStyles.paragraph }>This is a paragraph</Text>
</View>
)
}
You don't have to use StyleSheet.create
in your global styles, you can also define a plain JS object as a lookup for values that are needed everywhere in the app:
export const colours = {
blue: '#ace',
green: '#070',
red: '#d00'
}
App.js
import { colours } from 'styles/globalStyles'
...
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colours.blue
}
})
๐ฑ Conditional Styling
Very often, the styles will depend on the state of the application. Again, there's multiple ways to conditionally apply different styles. As an example, I have some state that is either true
or false
, which is visually represented by the border colour of the <View>
container.
To keep all the container styles, and only define a different border colour, pass an array of style objects:
import { StyleSheet, View } from 'react-native';
export default function App(){
const [ bool, setBool ] = useState(true);
return (
<View style={[ styles.container, { borderColor: bool ? 'green' : 'red' } ] }></View>
)
}
Looks messy, it's hard to read and maintain, and again, the object is recreated with every render. A better way is to define the styles in StyleSheet.create
:
import { StyleSheet, View } from 'react-native';
export default function App(){
const [ bool, setBool ] = useState(true);
return (
<View style={[ styles.container, bool ? styles.true : styles.false ]}></View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ace',
borderWidth: '4'
},
true: {
borderColor: 'red'
}
false: {
borderColor: 'green'
}
})
I still don't find this particularly awesome, it just looks cluttered. I've searched around a bit and came across this popular package: styled-components
๐ฑ React Native styled-components
In short, you can define custom components that are based on React Native's core components and write styles for them with CSS syntax using template strings. You can even pass props, which allows to conditionally style React Native components a little more in the familiar React way. An example for a custom <View>
component:
import styled from 'styled-components/native';
export default function App(){
const [ bool, setBool ] = useState(true);
return (
<CustomView borderCol={bool} />
)
}
const CustomView = styled.View`
flex: 1;
background-color: '#ace';
border-width: 4px;
border-color: ${props => props.borderCol ? 'green' : 'red'}
`
Note that although you can write the styles in CSS syntax, you can't use all CSS properties. Sometimes you have to go for platform-specific alternatives instead. Trying to apply a box-shadow
to a component will throw an error, Android uses a property elevation
for this, taking a number as value.
That's it for the basics of styling React Native components.
Next: How to use custom fonts.
๐ฑ Resources
React Native docs: Style props
How to use styled-components with React Native
๐ฑ Thanks for reading!
If you find any errors or have additions, questions or just want to say hi, please leave a comment below, or get in touch via my website jsdisco.dev or Twitter.
Keep calm & code ๐