Skip to content
Native Animation
Tilted Marquee Carousel animation preview

Tilted Marquee Carousel

An infinite welcome carousel that fans portrait posters across a color-shifting cinematic background.

$9 for this animation

Checkout opens soon. Leave your email and we will tell you the moment you can buy it.

One email when checkout opens. No spam.

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

npx nativeanimation add tilted-marquee-carousel

About this animation

An infinite welcome carousel that fans portrait posters across a color-shifting cinematic background.

How it works

  1. The component measures its own container and derives the cards, spacing, typography, and controls from that width and height.
  2. One continuous offset shared value drives every card. Three copies of the image list cover the viewport while modular positioning keeps the row visually seamless.
  3. A UI-thread frame callback advances the row at the requested point-per-second speed. A pan takes over the same offset, releases into decay, and eases back to cruising speed.
  4. The centered index is derived from the offset. Two blurred expo-image layers crossfade when that index changes, avoiding a live blur effect.
  5. Each card derives its fan rotation, vertical drop, scale, and layer order from its horizontal distance to the center.

Why this one

Unlike a passive marquee, this carousel lets the viewer grab the moving row without a jump, coast with momentum, and return smoothly to its original speed. A tap pauses or resumes it. Reduced Motion replaces continuous movement with deliberate tap pagination, and tintFor can give each background a controlled brand color without image processing.

Install

npx expo install expo-image expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Usage

import TiltedMarqueeCarousel from './TiltedMarqueeCarousel';

export function WelcomeScreen() {
  return (
    <TiltedMarqueeCarousel
      images={[
        require('./assets/poster-1.jpg'),
        require('./assets/poster-2.jpg'),
        require('./assets/poster-3.jpg'),
      ]}
    />
  );
}

Customize its motion, color, typography, and action:

import { useRef } from 'react';
import TiltedMarqueeCarousel, {
  type TiltedMarqueeCarouselRef,
} from './TiltedMarqueeCarousel';

export function WelcomeScreen() {
  const carouselRef = useRef<TiltedMarqueeCarouselRef>(null);

  return (
    <TiltedMarqueeCarousel
      ref={carouselRef}
      images={posters}
      eyebrow="Meet the collection"
      title="Paper Moon"
      subtitle="Independent illustration, selected with care."
      ctaLabel="Browse posters"
      speed={46}
      tilt={7}
      tintFor={(index) => palette[index]}
      fontFamily="YourSansFont"
      titleFontFamily="YourDisplayFont"
      onActiveChange={(index) => trackPoster(index)}
      onCtaPress={openCollection}
    />
  );
}

The forwarded ref exposes pause() and resume().

Props

PropTypeDefaultDescription
imagesImageSourcePropType[]RequiredPortrait images displayed in the infinite marquee.
eyebrowstring'Welcome to'Small introductory line above the title.
titlestring'Gallery'Main welcome title.
subtitlestring'A growing collection of bold illustrated posters, handpicked every week.'Supporting copy below the title.
ctaLabelstring'Start exploring'Primary action label.
speednumber38Automatic marquee speed in points per second.
tiltnumber9Maximum card rotation in degrees.
tintFor(index: number) => string—Returns an optional tint for each background image.
fontFamilystringSystem fontFont for supporting copy and controls.
titleFontFamilystringSystem fontFont for the main title.
onCtaPress() => void—Called when the primary action is pressed.
onActiveChange(index: number) => void—Called when a new image reaches the center.
styleStyleProp<ViewStyle>—Outer-container style.
testIDstring—Test identifier for the outer container.

Compatibility

  • Expo SDK 57
  • React Native 0.86
  • Reanimated 4.5 and Worklets 0.10
  • iOS: supported, not yet verified on a device
  • Android: supported, not yet verified on a device
  • Web: supported, not yet verified
  • Works in Expo Go because its native dependencies are included in the SDK

Accessibility

The primary action is exposed as a labeled button, and the carousel exposes adjustable increment and decrement actions for screen readers. Its hint explains the available touch behavior. With Reduced Motion enabled, continuous movement and transition animations stop; each tap advances exactly one poster.