react-native-skia-layout
v0.1.0
Published
Bring Flexbox layouts, positioning, and sizing to React Native Skia using Yoga.
Downloads
211
Maintainers
Readme
react-native-skia-layout
Flexbox layouts for React Native Skia. Position and size Skia shapes, text, images, and SVGs using familiar flexbox props, powered by React Native's layout engine, Yoga.

Why?
React Native Skia provides powerful rendering primitives, but positioning multiple elements and manually computing x/y for every element gets painful quickly, especially with nested containers, wrapping rows, and absolute positioning.
This let's you write Skia components the same way you already write React Native components.
Installation
npm install react-native-skia-layout react-native-nitro-modules @shopify/react-native-skiaExpo
This library works with Expo development builds and EAS Build. It does not run in Expo Go.
Web is not supported — there is no JS/WASM fallback for the native layout engine.
Setup
Use a development build (
expo-dev-client), not Expo Go.Install with
expo installso versions align with your SDK:
npx expo install expo-dev-client @shopify/react-native-skia react-native-nitro-modules react-native-skia-layout- Enable the New Architecture (required by Nitro Modules). On Expo SDK 53+ this is on by default; otherwise set it in
app.json:
{
"expo": {
"newArchEnabled": true
}
}For older Expo SDKs below 54 set the iOS deployment target to 16.0+ (required for Nitro's C++ interop). Expo SDK 54+ already defaults to 16.4. Use
expo-build-properties:Generate native projects and run:
npx expo prebuild
npx expo run:ios # or npx expo run:androidOr build a dev client with EAS Build.
After adding or updating this package, rebuild your development client (npx expo prebuild --clean if native linking fails).
Version alignment
Match your Expo SDK's React Native version to this library's peer range (react-native >= 0.76.0). Use npx expo install rather than npm install directly to avoid version mismatches.
Quick start
import {
FlexCanvas,
FlexLayout,
LayoutCircle,
LayoutRect,
} from 'react-native-skia-layout';
export function RowExample() {
return (
<FlexCanvas width={340} height={400} style={{ backgroundColor: 'coral' }}>
<FlexLayout
direction="row"
justifyContent="space-between"
alignItems="center"
gap={10}
wrap="wrap"
>
<LayoutCircle r={10} color="red" />
<LayoutCircle r={10} color="blue" />
<LayoutRect width={40} height={40} color="green" />
</FlexLayout>
</FlexCanvas>
);
}How it works
FlexCanvas— A SkiaCanvaswith a root layout node. Pass explicitwidthandheightto define the layout viewport.FlexLayout— A flex container. Nests like a<View>withflexDirection,justifyContent,alignItems, etc.- Layout components — Skia primitives that participate in layout and render at their computed position.
debug- Draws a stroke around elements computed bounds. Good for visualising layout bounds.
Limitations
Animated props are not supported yet. Layout props (width, height, flex, gap, margin, etc.) must be plain JavaScript values, not Reanimated SharedValues or other Skia animated types. Changing layout currently triggers a React re-render and a full layout pass; driving layout from the UI thread per frame is not implemented.
API
Components
| Component | Description |
|---|---|
| FlexCanvas | Root canvas + layout root. Requires width and height. |
| FlexLayout | Flex container for nesting children. |
| LayoutRect | Sized rectangle |
| LayoutRoundedRect | Rounded rectangle |
| LayoutCircle | Circle (sized by r) |
| LayoutOval | Ellipse (width × height) |
| LayoutPath | SVG path string |
| LayoutPoints | Polyline / point drawing |
| LayoutImage | Skia Image |
| LayoutSvg | Skia SVG |
| LayoutText | Single-line text (measured via font.measureText) |
| LayoutParagraph | Multi-line rich text via Skia Paragraph |
Each layout component accepts the underlying Skia props (color, path, font, etc.) plus layout props below.
Container props (FlexLayout)
| Prop | Type | Default |
|---|---|---|
| direction | 'row' | 'column' | 'row-reverse' | 'column-reverse' | 'row' |
| flex | number | — |
| flexGrow | number | — |
| flexShrink | number | — |
| flexBasis | number | — |
| width / height | number | — |
| gap | number | — |
| wrap | 'nowrap' | 'wrap' | 'wrap-reverse' | — |
| justifyContent | 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | — |
| alignContent | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'space-between' | 'space-around' | 'space-evenly' | — |
| alignItems | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline' | — |
| padding | number | { top?, right?, bottom?, left? } | — |
| margin | number | { top?, right?, bottom?, left? } | — |
| position | 'relative' | 'absolute' | 'static' | — |
| left / top / right / bottom | number | — |
| debug | boolean | false |
| debugColor | string | — |
Node props (layout primitives)
Shared across most Layout* components:
| Prop | Type |
|---|---|
| flex | number |
| width / height | number |
| margin | number | { top?, right?, bottom?, left? } |
| padding | number | { top?, right?, bottom?, left? } (where supported) |
| position | 'relative' | 'absolute' | 'static' |
| left / top / right / bottom | number |
| debug | boolean |
| debugColor | string |
Debug mode

Pass debug to any FlexLayout or supported Layout* component to draw a stroke around its computed bounds. Good for visualising layout bounds:
<LayoutOval width={45} height={65} color="green" debug />Examples
The example/ app demonstrates:
- Row layout with
space-betweenand wrap - Column layout with centered alignment
- Nested row/column containers
- Absolute positioning
- Text and paragraph layout
Run it from the repo root:
yarn example ios # or androidContributing
License
MIT
Made with create-react-native-library
