0
0
React Nativemobile~20 mins

Parallax scrolling in React Native - Mini App: Build & Ship

Choose your learning style9 modes available
Build: ParallaxScrollScreen
A screen that shows a parallax scrolling effect with a header image that moves slower than the content below.
Target UI
┌───────────────────────────────┐
│           HEADER IMAGE         │
│  (moves slower when scrolling) │
├───────────────────────────────┤
│ Item 1                        │
│ Item 2                        │
│ Item 3                        │
│ ...                          │
│ Item N                        │
└───────────────────────────────┘
Use a ScrollView with a header image at the top
The header image should shrink or move slower than the scroll content to create a parallax effect
Below the header image, show a list of at least 10 text items
The header image height should be about 200 pixels initially
The parallax effect should be smooth and visually clear
Starter Code
React Native
import React from 'react';
import { ScrollView, View, Text, Image, StyleSheet } from 'react-native';

export default function ParallaxScrollScreen() {
  return (
    <ScrollView>
      {/* TODO: Add header image with parallax effect here */}
      <View style={styles.content}>
        {/* TODO: Add list items here */}
      </View>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  content: {
    padding: 16
  }
});
Task 1
Task 2
Solution
React Native
import React, { useRef } from 'react';
import { Animated, ScrollView, View, Text, Image, StyleSheet, Dimensions } from 'react-native';

const HEADER_HEIGHT = 200;
const SCREEN_WIDTH = Dimensions.get('window').width;

export default function ParallaxScrollScreen() {
  const scrollY = useRef(new Animated.Value(0)).current;

  const headerTranslate = scrollY.interpolate({
    inputRange: [0, HEADER_HEIGHT],
    outputRange: [0, -HEADER_HEIGHT / 2],
    extrapolate: 'clamp'
  });

  return (
    <View style={styles.container}>
      <Animated.ScrollView
        contentContainerStyle={{ paddingTop: HEADER_HEIGHT }}
        scrollEventThrottle={16}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: scrollY } } }],
          { useNativeDriver: true }
        )}
      >
        <View style={styles.content}>
          {[...Array(15).keys()].map(i => (
            <Text key={i} style={styles.itemText}>Item {i + 1}</Text>
          ))}
        </View>
      </Animated.ScrollView>

      <Animated.View
        style={[
          styles.header,
          { transform: [{ translateY: headerTranslate }] }
        ]}
      >
        <Image
          source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
          style={styles.headerImage}
          resizeMode="cover"
          accessible={true}
          accessibilityLabel="Header image with parallax effect"
        />
      </Animated.View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  header: {
    position: 'absolute',
    top: 0,
    width: SCREEN_WIDTH,
    height: HEADER_HEIGHT,
    overflow: 'hidden',
    zIndex: 1
  },
  headerImage: {
    width: '100%',
    height: HEADER_HEIGHT
  },
  content: {
    backgroundColor: '#fff',
    paddingHorizontal: 16
  },
  itemText: {
    fontSize: 18,
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc'
  }
});

We use React Native's Animated API to create a smooth parallax effect. The scrollY animated value tracks the vertical scroll position. We interpolate this value to move the header image upwards but at half the speed of the scroll, creating the parallax effect.

The header image is positioned absolutely at the top, behind the scroll content. The scroll content has padding at the top equal to the header height so the list items start below the image.

This approach keeps the UI smooth and responsive, and the image moves slower than the content, which is the essence of parallax scrolling.

Final Result
Completed Screen
┌───────────────────────────────┐
│  [Header Image]               │
│  (moves slower when scrolling)│
├───────────────────────────────┤
│ Item 1                        │
│ Item 2                        │
│ Item 3                        │
│ Item 4                        │
│ Item 5                        │
│ Item 6                        │
│ Item 7                        │
│ Item 8                        │
│ Item 9                        │
│ Item 10                       │
│ Item 11                       │
│ Item 12                       │
│ Item 13                       │
│ Item 14                       │
│ Item 15                       │
└───────────────────────────────┘
When the user scrolls up, the header image moves up but slower than the list, creating a parallax effect.
The list items scroll normally below the header image.
The header image stays visible behind the content as the user scrolls.
Stretch Goal
Add a fade-out effect on the header image as the user scrolls down.
💡 Hint
Use the scrollY animated value to interpolate opacity from 1 to 0 as the user scrolls past the header height.