DEV Community

loading...
Cover image for OhSnap! Manage Global Styles In React Native

OhSnap! Manage Global Styles In React Native

Gedalya Krycer
Front-End Developer and Designer with a focus on React.
・3 min read

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

Discussion (0)