# How to Create a Custom Carousel for Your FlutterFlow App

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 15-20 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

Use FlutterFlow's PageView widget configured for horizontal scrolling to build a swipeable carousel. Each child is a Container with a background Image, gradient overlay, and text. Add dot indicators using a Row of Containers with Conditional Styling tied to the PageView Controller's current page index. Enable auto-scroll with an On Page Load loop action that waits three seconds then animates to the next page.

## Building a Swipeable Carousel in FlutterFlow

Carousels are used for hero banners, onboarding slides, product showcases, and promotional content. FlutterFlow's PageView widget is the foundation for building carousels — it supports horizontal swiping, page snapping, and controller-based navigation. This tutorial builds a complete image carousel with indicators and auto-scroll.

## Before you start

- A FlutterFlow project open in the builder
- Images for carousel slides (uploaded as assets or hosted URLs)
- A Firestore collection for dynamic slides (optional)

## Step-by-step guide

### 1. Add a PageView widget configured for horizontal scrolling

Drag a PageView widget from the Widget Palette onto your page. In the Properties Panel, set Scroll Direction to Horizontal and enable Page Snapping. Set the height to your desired slide height (e.g., 220 for a banner or 400 for a hero). Leave width at infinity to fill the parent. PageView creates multiple children pages that the user swipes between, each snapping into place.

**Expected result:** A horizontal PageView appears on the page that can hold multiple slide children.

### 2. Design each carousel slide with an image, gradient, and text overlay

Inside the PageView, add a Container child for each slide. Set the Container's decoration to an Image background (choose your slide image as a DecorationImage with BoxFit.cover). Add a second decoration layer: a linear gradient from transparent at the top to black at 60% opacity at the bottom. Inside the Container, add a Column (mainAxisAlignment: end) with a Text widget for the slide title (white, Headline Small) and a subtitle Text (white, Body Small). This creates a professional image card with readable text over the gradient.

**Expected result:** Each slide shows a full-bleed image with a bottom gradient and white text overlay.

### 3. Add dot indicators below the carousel tied to the active page

Below the PageView, add a Row with mainAxisAlignment set to center. Add one small Container per slide (width 8, height 8, borderRadius 4 for a circle). For the active dot, use a wider Container (width 24) with your Primary theme color. Set Conditional Styling on each dot: if the PageView Controller's current page index equals this dot's index, apply the active style (wider, colored). Otherwise, apply the inactive style (small, grey). Bind the page index using the PageView's controller reference.

**Expected result:** Dots below the carousel highlight the currently active slide and update as the user swipes.

### 4. Enable auto-scroll with a timed loop in On Page Load

Open the Action Flow for the page's On Page Load trigger. Add a Loop action with a large iteration count (e.g., 999). Inside the loop body, add a Wait action set to 3000 milliseconds (3 seconds). After the wait, add an Animate to Next Page action targeting your PageView widget (select it by name). If the PageView is on the last page, it cycles back to the first. This creates an infinite auto-scrolling carousel that still allows manual swiping.

**Expected result:** The carousel automatically advances to the next slide every 3 seconds, cycling back to the first after the last slide.

### 5. Populate slides dynamically from a Firestore banners collection

Create a Firestore collection called banners with fields: title (string), subtitle (string), imageUrl (string), actionUrl (string), order (int). Add documents for each slide. On the PageView, enable Generate Dynamic Children and bind it to a Backend Query on the banners collection sorted by order ascending. Map each child Container's image to the imageUrl field, title Text to the title field, and add an On Tap action that uses Launch URL with the actionUrl field.

**Expected result:** Carousel slides are generated from Firestore data and can be updated without modifying the app.

## Complete code example

File: `FlutterFlow Carousel Setup`

```text
WIDGET TREE:
  Column
    ├── PageView (height: 220, horizontal, page snapping: on)
    │     ├── Container (slide 1)
    │     │     ├── Decoration: Image (banner1.jpg, BoxFit.cover)
    │     │     ├── Decoration: LinearGradient (transparent → black 60%)
    │     │     └── Column (mainAxisAlignment: end)
    │     │           ├── Padding (16px)
    │     │           ├── Text: "Summer Sale" (white, Headline Small)
    │     │           └── Text: "Up to 50% off" (white, Body Small)
    │     ├── Container (slide 2) ... same structure
    │     └── Container (slide 3) ... same structure
    └── Padding (top: 12)
          └── Row (mainAxisAlignment: center, spacing: 6)
                ├── Container (active dot: w24 h8, borderRadius 4, Primary color)
                ├── Container (inactive dot: w8 h8, borderRadius 4, grey)
                └── Container (inactive dot: w8 h8, borderRadius 4, grey)

DOT INDICATOR CONDITIONAL STYLING:
  Each dot checks: PageView.currentPage == thisIndex
  Active:   width 24, color Theme.primary
  Inactive: width 8, color grey300

AUTO-SCROLL ACTION FLOW (On Page Load):
  1. Loop (iterations: 999)
     a. Wait: 3000ms
     b. Animate to Next Page (target: PageView)

FIRESTORE DATA MODEL (for dynamic slides):
  Collection: banners
  Fields: title, subtitle, imageUrl, actionUrl, order (int)
  Query: order ascending
```

## Common mistakes

- **Setting a fixed height without considering image aspect ratios** — If slide images have different aspect ratios, some crop more than others, creating inconsistent layouts. Tall images lose sides, wide images lose tops and bottoms. Fix: Use images with a consistent aspect ratio (e.g., all 16:9). Set the PageView height to match that ratio relative to the screen width. Crop images before uploading.
- **Not enabling Page Snapping on the PageView** — Without page snapping, slides stop mid-swipe and users see partial slides on both sides. The carousel feels broken and unprofessional. Fix: Enable Page Snapping in the PageView Properties Panel so each swipe lands precisely on a full slide.
- **Hardcoding slide content instead of using dynamic data** — Marketing teams need to update carousel banners frequently. Hardcoded slides require opening FlutterFlow and republishing the app for every change. Fix: Store slide data in a Firestore banners collection and use Generate Dynamic Children on the PageView. Updates happen instantly without app changes.

## Best practices

- Use Page Snapping on the PageView so slides land precisely on each swipe
- Add a gradient overlay on image slides so white text is always readable
- Keep auto-scroll interval between 3 and 5 seconds — too fast is disorienting
- Store carousel content in Firestore for easy marketing team updates
- Use consistent image aspect ratios across all slides to prevent cropping issues
- Make dot indicators wide for active and small for inactive to clearly show position
- Add On Tap actions on slides to make them tappable for promotions or navigation

## Frequently asked questions

### Can I use the carousel for onboarding screens?

Yes. Use the same PageView + dot indicator pattern for onboarding. Add a Skip button and a Done button on the last slide instead of auto-scroll.

### How do I make the carousel loop infinitely?

FlutterFlow's built-in Animate to Next Page wraps to the first slide after the last. For seamless infinite scroll without visible wrap, you need a Custom Widget with a PageController that jumps back programmatically.

### Can I add different tap actions to each slide?

Yes. When using dynamic children from Firestore, include an actionUrl field in each banner document. On the Container's On Tap, use Launch URL or Navigate with the actionUrl value.

### Does auto-scroll stop when the user manually swipes?

No — the loop continues running. To pause on user interaction, you would need a Custom Widget that listens to PageController scroll events and pauses the timer.

### How many slides should a carousel have?

Best practice is 3 to 5 slides. More than 5 means most users never see the later slides. If you have more content, consider a different layout like a grid or list.

### Can RapidDev help build an advanced carousel component?

Yes. RapidDev can create a Custom Widget carousel with infinite loop, pause-on-touch, swipe velocity detection, and parallax effects that go beyond the built-in PageView.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-carousel-for-your-flutterflow-app
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-carousel-for-your-flutterflow-app
