A photo header glides slower than the content, then a title bar fades in.
Installation
One command copies the source into your app — you own the code and can change anything.
Usage
useKit(). Wrap your app in <KitProvider accent="#6366f1" radius={14}> to re-skin every component at once.Props
| Prop | Type | Default |
|---|---|---|
| children The screen's content, under the header. | ReactNode | — |
| header Fills the header area: a photo, a map, a gallery (wins over headerImage). | ReactNode | — |
| headerImage Shortcut for a full-bleed header photo. | ImageSourcePropType | — |
| headerAccessibilityLabel Describes headerImage for screen readers (skipped when omitted). | string | — |
| headerHeight Header height, including the part under the status bar. | number | 300 |
| headerSpeed How the header moves while scrolling up: 0 scrolls with the content, 1 stays pinned while the content slides over it. | number | 0.5 |
| stretch iOS: pulling down stretches the header to fill the gap, anchored at the top. Turn off with a refreshControl. | boolean | true |
| headerOverlay Pinned to the bottom of the header (a title over the photo); lifts and fades as it scrolls away, over a bottom scrim. | ReactNode | — |
| title Ready-made top bar (theme background, hairline, centred title) that fades in once the header has scrolled under it. | string | — |
| bar Your own bar instead: fills the bar area (topInset included) and fades in the same way. Decorative — buttons go in barLeft / barRight. | ReactNode | — |
| barLeft / barRight Buttons pinned to the bar, visible over the photo too: each child sits on a round theme-coloured bubble that melts into the bar. Pass an array for several. | ReactNode | — |
| barHeight Height of the bar row, below topInset. | number | 52 |
| topInset Space above the bar for the status bar / notch — pass your safe-area top inset. | number | 0 |
| contentContainerStyle Style for the content under the header (padding, gap, background — theme background by default). | StyleProp<ViewStyle> | — |
| style Style for the outer frame (size, margins, radius). Fills its parent by default. | StyleProp<ViewStyle> | — |
| onScroll JS handler called alongside the native parallax event. For UI-thread effects use useParallaxScroll().scroll instead of your own Animated.event. | (e) => void | — |
| ref Forwarded to the scroll view, so you can call scrollTo. | Ref<ScrollView> | — |
| …ScrollView props Everything else is passed to the scroll view (vertical only): refreshControl, onScrollEndDrag, nestedScrollEnabled… | ScrollViewProps | — |
| ParallaxImage.source The photo. | ImageSourcePropType | — |
| ParallaxImage.height Frame height. | number | 200 |
| ParallaxImage.speed How much slower than its frame the photo moves: 0 still, 1 fixed on screen, negative the other way. | number | 0.3 |
| ParallaxImage.radius Corner radius of the frame. | number | radius.lg |
| ParallaxImage.scrim Bottom gradient so white text reads on the photo. | boolean | on with children |
| ParallaxImage.children Content over the photo, aligned to the bottom (a caption, a tag). | ReactNode | — |
| ParallaxImage.accessibilityLabel Describes the photo for screen readers. | string | — |
| ParallaxImage.style / imageStyle Style for the frame / for the photo itself. | StyleProp<ViewStyle> / StyleProp<ImageStyle> | — |
| ParallaxView.speed Offset relative to the scroll: positive lags behind the content, negative leads it. | number | 0.2 |
| ParallaxView.children / style What drifts, and its style (the transform is taken by the parallax). | ReactNode / StyleProp<ViewStyle> | — |
| useParallaxScroll() The live scroll offset (native-driver friendly), viewport size and content size for your own effects; null outside a ParallaxScrollView. | () => { scroll, viewport, contentHeight, contentRef } | null | — |
Behaviour & accessibility
- Motion
- The header lags behind the scroll and darkens as it leaves. The bar, title and button bubbles fade in once it has scrolled under the bar.
- Touch
- On iOS, pulling down past the top stretches the header to fill the gap. Set stretch to false when you use a refreshControl.
- Reduced motion
- With Reduce Motion on, the header, ParallaxImage and ParallaxView parallax offsets switch off; the stretch and the fades stay.
- Screen readers
- The bar comes first in reading order and its title is a header. Header and ParallaxImage photos are labelled images only when you give them a label.
- Platforms
- The scroll offset drives everything through a native Animated.event, so there is no JS work while scrolling.
Source
Did you like the content?

