Organizing Styles in React Native
The nice thing about styles in React Native is that everything is JavaScript. React Native uses a JavaScript class called StyleSheet
that resembles normal CSS in many ways, but there are some key differences:
- camelCase instead of kebab-case for style properties
- make use of JavaScript constants and functions to organize and calculate our styles
- style property values in StyleSheets need to be strings or numbers (but you can still use js constants and/or functions to declare them)
- instead of pixels, React Native uses “units” that get converted into pixels
- no shortcuts for padding or margin, (i.e. need to explicitly set
paddingTop
andpaddingRight
). – Note that you can usepaddingVertical
/paddingHorizontal
- no media queries, instead just use Flexbox (click here for a deep dive into on Flexbox in React Native)
In many React Native projects, styles have the tendency to get messy very quickly. That’s because in React Native, every component accepts a “style” prop where these are defined. In my experience, this encourages developers to define styles within individual component files, or worse, to write inline styles on the components themselves.
Defining styles and writing inline styles will inevitably lead to a variety of issues around maintenance, consistency, and organization.
Organizing styles in React Native
We should completely refrain from writing styles in our components. So, where to define our styles if not in the component itself? A nice approach is to create a folder for each component or set of components.
In our component’s subdirectory, we can add a file called style.js
. In here, create the component-specific style sheet which we will ultimately import into our component file. With this approach, we’ll have successfully abstracted our styles out of our component code. Awesome!
While that’s a huge improvement from styles being defined inside our components, we can still do better. With the above approach, we are able to create styled components that can easily be reused and maintained. However, there will likely be a lot of unnecessarily repeated styles throughout our various components’ style sheets.
This causes obvious problems with maintainability, since if one recurring style changes, it will need to be updated everywhere as opposed to one place.
Creating a simple base style sheet
Solve maintainability challenges by breaking generic base styles out into a higher level module that can be used when we create specific component stylesheets. Here is an example of a simple base style sheet that we can use to create component-specific stylesheets:
Our base styles module:
// app/styles/base.js import {StyleSheet, Dimensions} from 'react-native' export const dimensions = { fullHeight: Dimensions.get('window').height, fullWidth: Dimensions.get('window').width } export const colors = { primary: '#226B74', secondary: '#254B5A', tertiary: '#5DA6A7' } export const padding = { sm: 10, md: 20, lg: 30, xl: 40 } export const fonts = { sm: 12, md: 18, lg: 28, primary: 'Cochin' }
We can now import our base styles above into our component specific stylesheets:
Our component’s stylesheet:
// app/components/panel/style.js import {colors, fonts, padding, dimensions} from '../../styles/base.js' export default const panelStyles = StyleSheet.create({ container: { paddingHorizontal: padding.sm, paddingVertical: padding.lg, width: dimensions.fullWidth }, header: { fontSize: fonts.lg, fontFamily: fonts.primary }, section: { paddingVertical: padding.lg, paddingHorizontal: padding.xl } })
Our component:
// app/components/panel/index.js import styles from './style.js' export default class Panel extends Component { render() { return ( <View style={styles.container}> <Text style={styles.header}>Basic Header</Text> <Text style={styles.section}>Basic Section Text</Text> </View> ) }
Let’s go a step further by improving our base styles that we are importing into our component style sheets. Add the following code to your base stylesheet:
Our base styles module:
// app/styles/base.js … // added below our colors, fonts, padding etc // base styles const baseStyles = { container: { paddingHorizontal: padding.sm, paddingVertical: padding.lg, width: dimensions.fullWidth }, header: { backgroundColor: 'transparent', fontSize: fonts.lg, fontFamily: fonts.primary, fontWeight: 'bold' }, section: { paddingVertical: padding.lg, paddingHorizontal: padding.xl }, } export default function createStyles(overrides = {}) { return StyleSheet.create({...baseStyles, ...overrides}) }
So, now our base styles module is exporting a createStyle
function by default. This function acts essentially the same as StyleSheet.create
, except that it also accepts optional style overrides. We could use it at its simplest inside our component like so:
Our component:
// app/components/panel/index.js import createStyles from '../../styles/base.js' // creates our default base stylesheet (no overrides) const styles = createStyles() export default class Panel extends Component { render() { return ( <View style={styles.container}> <Text style={styles.header}>Basic Header</Text> <Text style={styles.section}>Basic Section Text</Text> </View> ) }
Let’s say we want to override some specific styles on this component. We want the section to have medium sized font with secondary text color. All we need to do is add some overrides to our createStyles function within our component stylesheet:
Our component stylesheet:
// app/components/panel/style.js import createStyles, {fonts, colors} from '../../styles/base.js' export default const panelStyles = createStyles({ section: { fontSize: fonts.md, color: colors.secondary } })
Our component:
// app/components/panel/index.js import style from './style.js' export default class Panel extends Component { render() { return ( <View style={styles.container}> <Text style={styles.header}>Basic Header</Text> <Text style={styles.section}>Basic Section Text</Text> </View> ) }
This implementation affords us a couple of good practices.
- We have base styles that will be used throughout our component-specific styles, making everything easier to maintain and update in the future.
- Component-specific styles are located right next to the component JavaScript file, so they are easy to find.
- We’ve avoided the unsightly inline styles in our components which makes them hard to read.
There you have it: a useful overview of how to organize styles in React Native. Let us know if you implement these processes, or suggest an update!
Originally published at revelry.co on December 27, 2017.