One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Gradients

CSS gradients on every platform with backgroundImage, and SwiftUI gradient views on iOS

For a gradient that looks the same on iOS, Android, and web, write it as a CSS string in the backgroundImage style of any View. React Native parses linear-gradient() and radial-gradient() and draws them behind the view’s content; on web the string is plain CSS.

For gradients CSS cannot express, or for gradients inside a SwiftUI layout, iOS has five views that draw SwiftUI’s own gradients: One.iOS.LinearGradient, RadialGradient, EllipticalGradient, AngularGradient, and MeshGradient.

Usage

import { View } from 'react-native'
function Scrim() {
return (
<View
style={{
height: 120,
backgroundImage: 'linear-gradient(to bottom, rgba(0,0,0,0.6), rgba(0,0,0,0))',
}}
/>
)
}

The gradient fills the view’s box and sits under its children, like a background color.

How it works

backgroundImage is part of React Native’s style system from 0.87, the version One builds on. React Native parses the string in JavaScript into color stops and a direction, and the native view draws the result in its background on both iOS and Android. On web, react-native-web passes the string to the element’s CSS untouched.

React Native also accepts backgroundImage as an array of gradient objects. That form works on iOS and Android, but react-native-web forwards the objects as they are and the browser draws nothing, so prefer the string in shared code.

The SwiftUI views are Fabric components. Each one hosts the matching SwiftUI gradient (LinearGradient(colors:startPoint:endPoint:) and its siblings) and has no size of its own: it fills the layout box that style gives it. Inside another One.iOS view, such as a ZStack, the gradient joins the parent’s SwiftUI tree instead of hosting itself.

The wrappers check their props in JavaScript before anything reaches native code. Colors must be sRGB hex strings, #RRGGBB or #RRGGBBAA; points and radii must be finite numbers. A bad value throws at render with a message naming the prop. On Android and web, One.iOS gradients throw that they need an iOS native build.

API reference

Every SwiftUI gradient also takes style, swiftStyle, testID, onLayout, and the accessibility label, hint, and value. Points are unit coordinates: { x: 0, y: 0 } is the top left corner and { x: 1, y: 1 } the bottom right.

One.iOS.LinearGradientTypeDescription
colors (required)readonly string[]Hex colors, spaced evenly from start to end.
readonly string[]Hex colors, spaced evenly from start to end.
startPointReadonly<{ x: number; y: number }> = { x: 0.5, y: 0 }Where the first color sits.
Readonly<{ x: number; y: number }> = { x: 0.5, y: 0 }Where the first color sits.
endPointReadonly<{ x: number; y: number }> = { x: 0.5, y: 1 }Where the last color sits.
Readonly<{ x: number; y: number }> = { x: 0.5, y: 1 }Where the last color sits.
One.iOS.RadialGradientTypeDescription
colors (required)readonly string[]Hex colors, from the center outward.
readonly string[]Hex colors, from the center outward.
centerReadonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
Readonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
startRadiusnumber = 0Where the first color starts, in points.
number = 0Where the first color starts, in points.
endRadius (required)numberWhere the last color ends, in points.
numberWhere the last color ends, in points.
One.iOS.EllipticalGradientTypeDescription
colors (required)readonly string[]Hex colors, from the center outward.
readonly string[]Hex colors, from the center outward.
centerReadonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
Readonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
startRadiusFractionnumber = 0Where the first color starts, as a fraction of the box.
number = 0Where the first color starts, as a fraction of the box.
endRadiusFractionnumber = 0.5Where the last color ends, as a fraction of the box.
number = 0.5Where the last color ends, as a fraction of the box.
One.iOS.AngularGradientTypeDescription
colors (required)readonly string[]Hex colors, swept once around the center.
readonly string[]Hex colors, swept once around the center.
centerReadonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
Readonly<{ x: number; y: number }> = { x: 0.5, y: 0.5 }The center, in unit coordinates.
angleReadonly<{ radians: number }> = { radians: 0 }Rotates where the sweep begins.
Readonly<{ radians: number }> = { radians: 0 }Rotates where the sweep begins.
One.iOS.MeshGradientTypeDescription
meshWidth (required)numberVertices per row, at least 2.
numberVertices per row, at least 2.
meshHeight (required)numberRows of vertices, at least 2.
numberRows of vertices, at least 2.
points (required)readonly Readonly<{ x: number; y: number }>[]meshWidth × meshHeight vertex positions, row by row.
readonly Readonly<{ x: number; y: number }>[]meshWidth × meshHeight vertex positions, row by row.
colors (required)readonly string[]One hex color per vertex, in the same order.
readonly string[]One hex color per vertex, in the same order.
backgroundstring = "#00000000"Fills the box outside the mesh.
string = "#00000000"Fills the box outside the mesh.
smoothsColorsboolean = trueBlend with curves rather than straight lines.
boolean = trueBlend with curves rather than straight lines.
colorSpace"device" | "perceptual" = "device"The color space for blending.
"device" | "perceptual" = "device"The color space for blending.

Platform differences

iOSAndroidWeb
CSS stringDrawn by React NativeDrawn by React NativeBrowser CSS
Gradient objectsDrawn by React NativeDrawn by React NativeNot drawn
SwiftUI gradientsYesThrowsThrows
Mesh gradientiOS 18 and laterThrowsThrows

Limits and gotchas

Examples

Fade text out at the bottom of a card

import { Text, View } from 'react-native'
function Preview({ body }: { body: string }) {
return (
<View style={{ height: 160, overflow: 'hidden' }}>
<Text>{body}</Text>
<View
pointerEvents="none"
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 48,
backgroundImage: 'linear-gradient(to bottom, rgba(255,255,255,0), #ffffff)',
}}
/>
</View>
)
}

The overlay sits on top of the text and fades to the card color. pointerEvents="none" keeps it from catching taps meant for the text.

Draw a progress ring on iOS

import { Platform, View } from 'react-native'
import { One } from 'one'
function Ring() {
if (Platform.OS !== 'ios') return <View style={{ width: 120, height: 120 }} />
return (
<View style={{ width: 120, height: 120, borderRadius: 60, overflow: 'hidden' }}>
<One.iOS.AngularGradient
colors={['#34C759', '#30B0C7', '#34C759']}
angle={{ radians: -Math.PI / 2 }}
accessibilityLabel="Activity ring"
style={{ flex: 1 }}
/>
</View>
)
}

Repeating the first color at the end closes the sweep without a seam. The angle starts it at twelve o’clock, and the rounded parent clips it to a circle.

Paint a mesh background on iOS 18

import { One } from 'one'
// three rows of three vertices, top to bottom
const points = [
{ x: 0, y: 0 }, { x: 0.5, y: 0 }, { x: 1, y: 0 },
{ x: 0, y: 0.5 }, { x: 0.6, y: 0.4 }, { x: 1, y: 0.5 },
{ x: 0, y: 1 }, { x: 0.5, y: 1 }, { x: 1, y: 1 },
]
const colors = [
'#1B1F3B', '#2E3A87', '#1B1F3B',
'#5B2C83', '#29B6F6', '#2E3A87',
'#1B1F3B', '#5B2C83', '#1B1F3B',
]
function Aurora() {
return (
<One.iOS.MeshGradient
meshWidth={3}
meshHeight={3}
points={points}
colors={colors}
style={{ flex: 1 }}
/>
)
}

A 3 × 3 mesh needs nine points and nine colors. Moving the middle point off center bends the blend toward it; the edge points stay on the border so the mesh covers the whole box.

Edit this page on GitHub.