Bird
Raised Fist0
React Nativemobile~20 mins

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

Choose your learning style10 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.

Practice

(1/5)
1. What is the main idea behind parallax scrolling in mobile apps?
easy
A. Scrolling is disabled to keep the background fixed.
B. All elements move at the same speed to keep the screen static.
C. Background images move slower than the foreground content to create depth.
D. Foreground images move slower than the background to focus attention.

Solution

  1. Step 1: Understand parallax scrolling concept

    Parallax scrolling means background moves slower than foreground to create a 3D effect.
  2. Step 2: Match the description to options

    Background images move slower than the foreground content to create depth correctly describes this effect, others do not.
  3. Final Answer:

    Background images move slower than the foreground content to create depth. -> Option C
  4. Quick Check:

    Parallax = background slower than foreground [OK]
Hint: Remember: background moves slower to create depth [OK]
Common Mistakes:
  • Confusing which layer moves slower
  • Thinking all layers move equally
  • Assuming scrolling is disabled
2. Which React Native code snippet correctly creates an animated value for parallax scrolling?
easy
A. const scrollY = new Animated.Value(0);
B. const scrollY = Animated.createValue(0);
C. const scrollY = Animated.Value();
D. const scrollY = Animated.Value(0);

Solution

  1. Step 1: Recall Animated.Value syntax

    The correct way to create an animated value is using new Animated.Value(initialValue).
  2. Step 2: Check each option

    const scrollY = new Animated.Value(0); uses correct syntax. Options A, B, and D have syntax errors or missing arguments.
  3. Final Answer:

    const scrollY = new Animated.Value(0); -> Option A
  4. Quick Check:

    Animated.Value needs 'new' and initial value [OK]
Hint: Use 'new Animated.Value(0)' to start animation value [OK]
Common Mistakes:
  • Omitting 'new' keyword
  • Not passing initial value
  • Using wrong method names
3. Given this code snippet, what will be the output behavior of the background image?
const scrollY = new Animated.Value(0);
const translateY = scrollY.interpolate({
  inputRange: [0, 100],
  outputRange: [0, -50],
  extrapolate: 'clamp'
});

// Used in style: { transform: [{ translateY }] }
medium
A. Background moves up the same distance as scroll.
B. Background moves down as user scrolls down.
C. Background stays fixed and does not move.
D. Background moves up half the scroll distance when scrolling down.

Solution

  1. Step 1: Understand interpolation mapping

    Input scroll from 0 to 100 maps to translateY from 0 to -50, so background moves up half the scroll.
  2. Step 2: Interpret transform effect

    Negative translateY moves background up, but only half the scroll distance, creating parallax.
  3. Final Answer:

    Background moves up half the scroll distance when scrolling down. -> Option D
  4. Quick Check:

    Interpolate outputRange controls movement amount [OK]
Hint: Check outputRange values to see movement scale [OK]
Common Mistakes:
  • Confusing positive/negative translateY direction
  • Assuming background moves same as scroll
  • Ignoring 'clamp' effect
4. Identify the error in this React Native parallax code snippet:
const scrollY = new Animated.Value(0);
const translateY = scrollY.interpolate({
  inputRange: [0, 100],
  outputRange: [0, 50],
  extrapolate: 'extend'
});

// Used in style: { transform: [{ translateY }] }
medium
A. Missing 'new' keyword when creating Animated.Value.
B. Using 'extrapolate: extend' can cause unwanted movement beyond input range.
C. Output range values should be negative to move background up.
D. Input range array must have three values.

Solution

  1. Step 1: Check extrapolate property effect

    'extend' allows output to go beyond outputRange if input exceeds inputRange, causing unwanted movement.
  2. Step 2: Verify other code parts

    Animated.Value uses 'new' correctly, outputRange can be positive, inputRange can have two values.
  3. Final Answer:

    Using 'extrapolate: extend' can cause unwanted movement beyond input range. -> Option B
  4. Quick Check:

    Use 'clamp' to restrict movement within range [OK]
Hint: Use 'clamp' to prevent movement beyond limits [OK]
Common Mistakes:
  • Confusing 'extend' with 'clamp'
  • Assuming outputRange must be negative
  • Thinking inputRange needs 3 values
5. You want to create a parallax effect where the background image moves slower vertically and also fades out as the user scrolls down. Which approach correctly combines these effects in React Native?
hard
A. Use one Animated.Value for scrollY, interpolate translateY for slower movement, and interpolate opacity from 1 to 0.
B. Use two separate Animated.Values for scroll position and opacity, updating both independently.
C. Animate translateY only; opacity cannot be animated with parallax.
D. Use scrollY Animated.Value but set opacity directly without interpolation.

Solution

  1. Step 1: Combine animations using one Animated.Value

    Using one scrollY Animated.Value allows interpolating multiple properties like translateY and opacity smoothly.
  2. Step 2: Interpolate translateY for slower movement and opacity for fade

    TranslateY outputRange uses smaller values for slower movement; opacity interpolates from 1 to 0 as scroll increases.
  3. Step 3: Avoid separate Animated.Values or direct opacity setting

    Separate values complicate sync; direct opacity without interpolation won't animate smoothly.
  4. Final Answer:

    Use one Animated.Value for scrollY, interpolate translateY for slower movement, and interpolate opacity from 1 to 0. -> Option A
  5. Quick Check:

    One Animated.Value + multiple interpolations = smooth combined effect [OK]
Hint: Use one Animated.Value with multiple interpolations for combined effects [OK]
Common Mistakes:
  • Using multiple Animated.Values causing unsynced animations
  • Not interpolating opacity, so fade is abrupt
  • Trying to animate opacity without Animated API
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard