Creating Gradient With React Native Linear Gradients and React Native SVG

SegunSegun
7 min read

Gradients let us display smooth transitions between two or more specified colours. Even though gradients are a popular component of CSS on the web, they are not supported in React Native at the time of writing this article so developers often rely on react-native-linear-gradient and react-native-svg whenever we need to implement gradients in React Native.

At the end of this article, you should be able to implement gradients in React Native.

Types of Gradient

There are three types of gradients; the linear gradient, the radial gradient, and the conic gradient. The linear gradients go in a linear direction and can be either down/up/left/right/diagonally. The Radial gradients on the other hand are defined by their centre while the Conic gradients are rotated around a centre point.

For this article though, we will be focusing on Linear and Radial gradients.

Linear Gradient

To begin, we will need to import LinearGradient. When building an app using react native, there are usually two workflows you can adopt. You have an option of using the Expo-managed workflow or the React Native CLI. If you settle for the former, you can import LinearGradient using the code snippet below:

import { LinearGradient } from 'expo-linear-gradient';

Otherwise, the following will suffice.

import LinearGradient from 'react-native-linear-gradient;

Nevertheless, whichever one you end up using, the implementation would not be any different.

The LinearGradient component accepts some props, namely: colors, locations, start and end. These props influence how a gradient is displayed. Let's take a quick look at each of these props before playing around with LinearGradient.

  • Colors: This is an array of colors that represent stops or positions in the gradient. At least two colors are required. Colors can be passed in different formats like name, hex values or even rgba. An example could look like this: colors={['rgba(0,0,0,0.8)', 'transparent']}

  • Locations: Locations is an array of numbers ranging from 0 - 1 that maps to the corresponding colors passed into LinearGradient. Each number in locations indicates a color-stop location where each respective color should be located. For example, if we have color with values {['red', 'orange', 'yellow' ]}, then location must contain three(3) values as well like {[0, 0.5, 0.6]} for example. Otherwise, the colors red, orange, and yellow will be distributed evenly if locations are not specified.

  • Start: This indicates where the gradient will start and takes in values in the form { x: number, y: number }, more like the x and y axis that make up the cartesian coordinate system. Coordinates declare the position that the gradient starts at, as a fraction of the overall size of the gradient, starting from the top left corner. Example: { x: 0.1, y: 0.1 } means that the gradient will start at 10% from the left and 10% from the top.

  • End: The end takes in values just like start. Like start, end indicates where the gradient will end. Example: { x: 1, y: 0.1 } means that the gradient will end at 10% from the left and 10% from the bottom.

Moving forward, we will refer to {x: 0, y: 0.5} for start position as x1, y1 and {x: 1, y: 0.5} for end as x2, y2.

Using react-native-linear-gradient, gradients can be created in either vertical, horizontal or diagonal/angular orientation. To create a gradient with a vertical orientation, we only need to provide the LinearGradient class with the color prop and maybe some style for the size of the container. We can also have a vertical orientation when x1 and x2 are equal and y1 and y2 differ

For horizontal orientation, the trick is to have a consistent start and end value for the y-axis. This simply means, when y1 and y2 are equal and x1 and x2 differ, we have a horizontal gradient.

To implement a linear gradient with diagonal orientation, we will need to set the same start value for x and y, and the same end value for x and y. What this means is when x1 and x2 differ and y1 and y2 differ we have a diagonal gradient.

import React from 'react';
import { View, StyleSheet } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';

export default function App() {
  return (
    <View style={styles.container}>
      <LinearGradient
          colors={['red', 'cyan', 'yellow' ]}
          style={styles.linearGradient}
        >
          <Text>Vertical orientation</Text>
        </LinearGradient>
      <LinearGradient
          colors={['red', 'cyan', 'yellow' ]}
          style={styles.linearGradient}
          start={{ x: 0, y: 0.5 }}
          end={{ x: 1, y: 0.5 }}
        >
          <Text>Horizontal orientation</Text>
        </LinearGradient>
      <LinearGradient
          colors={['red', 'cyan', 'yellow' ]}
          style={styles.linearGradient}
          start={{ x: 0, y: 0 }}
          end={{ x: 1, y: 1 }}
        >
          <Text>Diagonal orientation</Text>
        </LinearGradient>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
    alignItems: 'center'
  },
  linearGradient: {
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: 5,
    height: 200,
    width: 200,
    marginVertical: 20
  },
});

Radial Gradient

As of the time of writing this, react-native-linear-gradient does not have support for the radial gradient. For us to implement a radial gradient, we will need to make use of react-native-svg.

To do this, we need to import some elements from react-native-svg like Defs, RadialGradient, Rect and Stop. There are a lot more imports from react-native-svg, but these are the only ones we would be needing for our example.

For context;

  • <Defs> is short for definitions. Its an element that contains definitions of special elements (such as gradients).

  • <RadialGradient> takes in some props like cx,cy,rx,ry,fx,fy and gradientUnits.The cx and cy and r props define the outermost circle and the fx and fy define the innermost circle. The gradientUnits an attribute defines the coordinate system used for attributes specified on the gradient elements.

  • <Rect> is an element used to create a rectangle and variations of a rectangle shape.

  • <Stop> element defines a color and its position to use on a gradient. This element is always a child of a <linearGradient> or <radialGradient>.

Now that we’ve familiarized ourselves with some of the properties, let's jump right straight to implementation by creating a file for the actual gradient code, named radial-gradient.tsx.

// radial-gradient.tsx

import React from 'react';
import Svg, {
    Defs,
    RadialGradient as SVGRadialGradient,
    Rect,
    Stop,
} from 'react-native-svg';

export type Color = {
    offset: string;
    color: string;
    opacity: string;
};

const RadialGradient = ({ colorList, x, y, rx, ry }: { colorList: Color[]; x: string; y: string; rx: string; ry: string; }) => {
    return (
        <Svg height="100%" width="100%">
            <Defs>
                <SVGRadialGradient
                    id="grad"
                    cx={x}
                    cy={y}
                    rx={rx}
                    ry={ry}
                    gradientUnits="userSpaceOnUse"
                >
                    {colorList.map((value, index) => (
                        <Stop
                            key={`RadialGradientItem_${index}`}
                            offset={value.offset}
                            stopColor={value.color}
                            stopOpacity={value.opacity}
                        />
                    ))}
                </SVGRadialGradient>
            </Defs>
            <Rect x="0" y="0" width="100%" height="100%" fill="url(#grad)" />
        </Svg>
    );
};

export default RadialGradient;

Let's proceed to import our new radial component into a parent component.

// App.tsx
import React from 'react';
import { View, StyleSheet } from 'react-native';
import RadialGradient from './radial-gradient';


const colorList = [
  { offset: '0%', color: '#08b44f', opacity: '1' },
  { offset: '50%', color: '#07af4d', opacity: '1' },
  { offset: '75%', color: '#08b44f', opacity: '0.8' },
  { offset: '100%', color: '#3ACA54', opacity: '0.5' }
];

const colorList2 = [
  { offset: '0%', color: '#08b44f', opacity: '0' },
  { offset: '50%', color: '#07af4d', opacity: '1' },
  { offset: '75%', color: '#08b44f', opacity: '0.5' },
  { offset: '100%', color: '#3ACA54', opacity: '0.8' }
];

const colorList3 = [
  { offset: '0%', color: '#08b44f', opacity: '1' },
  { offset: '50%', color: '#07af4d', opacity: '1' },
  { offset: '75%', color: '#08b44f', opacity: '1' },
  { offset: '100%', color: '#3ACA54', opacity: '1' }
];

const App = () => {
  return (
    <View style={styles.container}>
      <View style={{ width: '100%', height: 200, marginBottom: 10 }}>
          <RadialGradient x={"50%"} y="50%" rx="50%" ry="50%" colorList={colorList} />
      </View>
      <View style={{ width: '100%', height: 200, marginBottom: 10 }}>
          <RadialGradient x={"50%"} y="50%" rx="50%" ry="50%" colorList={colorList2} />
      </View>
      <View style={{ width: '100%', height: 200, marginBottom: 10 }}>
          <RadialGradient x={"50%"} y="50%" rx="50%" ry="50%" colorList={colorList3} />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
    alignItems: 'center'
  },
});
export default App;

Once you save your changes without any errors, you should have a view looking like this:

Conclusion

The few examples covered in this article are just a tiny fraction of the amazing things that can be done using gradients. I've only come up with these examples as I played around with both libraries covered in this article, and I'm sure I've barely scratched the surface. Hopefully, you get to tinker around with some code yourself and create magic.

0
Subscribe to my newsletter

Read articles from Segun directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Segun
Segun