DEV Community

Cover image for OhSnap! Manage Global Styles In React Native
Gedalya Krycer
Gedalya Krycer

Posted on

OhSnap! Manage Global Styles In React Native

The "OhSnap!" series explores bite-sized tips that you can apply today.


Introduction

One of the big adjustments I had to make when using React Native, is not relying on CSS.

Sure, there are still "CSS-like" properties that use the JS-based StyleSheet method, but they are not the same.

For example, since everything is locally scoped, we can’t easily set global styles.

Well, not quite...

Here are two ways to handle global styles that are actually pretty simple, yet powerful.


Method A: Custom Styled Component

Using a standard React pattern, we will create a custom component for the element we want to style globally.

Within this component, we can set default styles and also use props to override those styles.

Then we can import and use this component anywhere in our project. If the styles need to change, only that component needs to be updated.

For example:

  • <HeaderOne /> could contain a bold <Text> element with a large font size.

  • <BodyText /> could contain a smaller, dark grey <Text> element.

  • <PrimaryButton /> could contain a <TouchableOpacity> element with a green background and uppercase text.

(This is a very similar concept to the styled-componets package.)

Aright! Enough talk. Let's see how it actually looks and set up a styled button we can use globally.

Step 1: Create base <PrimaryButton /> component

Our component should accept props and import some standard React Native default components to create the base structure & functionality.

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      onPress={() => props.pressHandler}
    >
     <Text>{props.title}</Text>
    </TouchableOpacity>
  );
};

export default PrimaryButton;
Enter fullscreen mode Exit fullscreen mode

Step 2: Add base styles

Using the StyleSheet method from React Native, set up some base styles for this button.

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      style={styles.btnContainer} 
      onPress={() => props.pressHandler}
    >
     <Text style={styles.text}>{props.title}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
    btnContainer: {
        paddingVertical: 3,
        paddingHorizontal: 10
        backgroundColor: 'green',
        justifyContent: 'center',
    },
    text: {
      color: 'white',
      fontSize: 20,
    }, 
});

export default PrimaryButton;
Enter fullscreen mode Exit fullscreen mode

Step 3: Spread local styles & prop styles

Use the spread operator to add all current styles and then any custom styles being passed in via props. This will allow additional styles to be added/overwritten.

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';


const PrimaryButton = props => {
  return (
    <TouchableOpacity 
      style={{...styles.btnContainer, ...props.containerStyle}}
      onPress={() => props.pressHandler}
    >
     <Text 
       style={{...styles.text, ...props.textStyle}}
     >
      {props.title}
     </Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
    btnContainer: {
        paddingVertical: 3,
        paddingHorizontal: 10
        backgroundColor: 'green',
        justifyContent: 'center',
    },
    text: {
      color: 'white',
      fontSize: 20,
    }, 
});

export default PrimaryButton;
Enter fullscreen mode Exit fullscreen mode

Step 4: Use <PrimaryButton /> anywhere in the project

Note how we are passing in a custom margin, via props. This will get applied to the button, in addition to the default local style we set up already.

import React from 'react';
import { StyleSheet, Text, View} from 'react-native';
import PrimaryButton from './components/PrimaryButton'


const ContactScreen = props => {
  return (
   <View>
    <Text>Contact Us</Text>
    •••
    <PrimaryButton 
      title="Submit"
      pressHandler={someCoolFunction}
      containerStyle={styles.btn}
      textStyle={styles.title}
    />
   </View>
  );
};

const styles = StyleSheet.create({
    btn: {
        marginTop: 10,
    },
    btnTitle: {
      color: 'grey',
    }, 
});

export default ContactScreen;
Enter fullscreen mode Exit fullscreen mode

Method B: Export Global Object

This next method can either be used instead of custom components or in conjunction with it.

The idea to store values for CSS properties inside of objects or variables that are exported from global files.

Let's take the example of how to work with colors. Imagine having to change the "Primary" brand color from blue to green. With the below method you just need to update that color in one file.

Step 1: Create a global styles folder

In the root of the src directory create a new folder called styles and add a new file called colors.js.

/src
|—— /styles
    |—— colors.js
Enter fullscreen mode Exit fullscreen mode

Step 2: Add property values.

Create and export an object within the colors file that holds the values

export default {
  primary: '#FFBB0B',
  primaryLight: '#FFDF8E',
  primaryDark: '#CB9303',
  secondary: '#63321C',
  secondaryLight: '#735243',
  secondaryDark: '#170F0C',
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Import and use the Colors file.

Now you can go to any file in your project and reference the colors you have set up in step 2 on any acceptable property.

If any time your brand colors change, these files will update automatically!

import React from 'react';
import { StyleSheet, Text, View} from 'react-native';
import colors from '../styles/colors'; <-----------


const ContactScreen = props => {
  return (
   <View style={styles.header}>
    <Text style={styles.headline}>Contact Us</Text>
   </View>
  );
};

const styles = StyleSheet.create({
    header: {
      flex: 1,
      backgroundColor: colors.secondaryLight, <-----------
    },
    headline: {
        color: colors.primary, <-----------
    },
});

export default ContactScreen;
Enter fullscreen mode Exit fullscreen mode

Thumbnail designed with Adobe Photoshop

Top comments (1)

Collapse
 
brett84c profile image
Brett Connolly

Starting my first major React Native project today and this was a huge help in laying the foundation for global styling and reusable components. Thank you so much!