Styling React Native Components

Styling React Native Components

ยท

4 min read

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 ๐Ÿ‘‹