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.
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.
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.
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.LinearGradient | Type | Description |
|---|---|---|
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.RadialGradient | Type | Description |
|---|---|---|
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 = 0 | Where the first color starts, in points. |
endRadius (required)numberWhere the last color ends, in points. | number | Where the last color ends, in points. |
| One.iOS.EllipticalGradient | Type | Description |
|---|---|---|
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 = 0 | Where 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.5 | Where the last color ends, as a fraction of the box. |
| One.iOS.AngularGradient | Type | Description |
|---|---|---|
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.MeshGradient | Type | Description |
|---|---|---|
meshWidth (required)numberVertices per row, at least 2. | number | Vertices per row, at least 2. |
meshHeight (required)numberRows of vertices, at least 2. | number | Rows 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 = true | Blend with curves rather than straight lines. |
colorSpace"device" | "perceptual" = "device"The color space for blending. | "device" | "perceptual" = "device" | The color space for blending. |
| iOS | Android | Web | |
|---|---|---|---|
| CSS string | Drawn by React Native | Drawn by React Native | Browser CSS |
| Gradient objects | Drawn by React Native | Drawn by React Native | Not drawn |
| SwiftUI gradients | Yes | Throws | Throws |
| Mesh gradient | iOS 18 and later | Throws | Throws |
style a width and height, or flex, or the view is zero sized.rgb(),
and theme colors, including the mesh background. backgroundImage strings take any CSS
color.accessibilityLabel when the colors carry meaning.colors:
initializers only, so there is no per-stop position. Repeat a color to hold
it longer, or use a CSS string with explicit stop positions.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.
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.
import { One } from 'one'
// three rows of three vertices, top to bottomconst 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.