---
title: "How to Build a Carousel or Slider in Framer"
description: "How to build a carousel or slider in Framer: native scroll-based sliders, code-based swipe carousels, and CMS-connected carousels for testimonials, products, and images."
canonical_url: "https://framerhub.io/blog/framer-carousel-slider-guide"
last_updated: "2026-09-22T00:00:00.000Z"
---

A **framer carousel** shows up in more places than people expect: product showcases, testimonial rows, image galleries, logo strips, featured content banners. Framer doesn't ship a single dedicated carousel component with dots, arrows, and autoplay built in, but there are several practical ways to build one depending on what you actually need.

This guide covers the native approach, a code-based custom carousel, and a CMS-connected carousel plugin, so you can pick based on how much control and CMS integration your specific use case needs.

---

## Option 1: Native horizontal Scroll component

Framer's Scroll component, set to horizontal direction, functions as a basic swipeable slider. Visitors drag or swipe through content placed in a row.

**What this gives you:** swipe/drag-based horizontal browsing, works on both desktop (trackpad, mouse drag) and mobile (touch swipe), zero code required.

**What it doesn't give you:** navigation dots, arrow buttons, autoplay, or snap-to-item behavior (content scrolls freely rather than settling on one item at a time). For a simple, low-friction slider where free-scrolling is fine, this is often enough.

**Best for:** image rows, logo strips, or simple content browsing where visitors are expected to swipe/drag rather than click through discrete "slides."

---

## Option 2: A code-based carousel with snap and controls

For a carousel that snaps to one item at a time and includes navigation dots and arrows, a code override gives full control:

```tsx
import type { ComponentType } from "react"
import { useState } from "react"
import { motion, AnimatePresence } from "framer-motion"

export function withSnapCarousel(items: any[]): (Component) => ComponentType {
    return (Component) => (props) => {
        const [index, setIndex] = useState(0)

        function next() {
            setIndex((i) => (i + 1) % items.length)
        }

        function prev() {
            setIndex((i) => (i - 1 + items.length) % items.length)
        }

        return (
            <div style={{ position: "relative", overflow: "hidden" }}>
                <AnimatePresence mode="wait">
                    <motion.div
                        key={index}
                        initial={{ opacity: 0, x: 40 }}
                        animate={{ opacity: 1, x: 0 }}
                        exit={{ opacity: 0, x: -40 }}
                        transition={{ duration: 0.35, ease: "easeOut" }}
                    >
                        <Component {...props} content={items[index]} />
                    </motion.div>
                </AnimatePresence>

                <button onClick={prev} style={{ position: "absolute", left: 12, top: "50%" }}>‹</button>
                <button onClick={next} style={{ position: "absolute", right: 12, top: "50%" }}>›</button>

                <div style={{ display: "flex", gap: 6, justifyContent: "center", marginTop: 12 }}>
                    {items.map((_, i) => (
                        <div
                            key={i}
                            onClick={() => setIndex(i)}
                            style={{
                                width: 8,
                                height: 8,
                                borderRadius: "50%",
                                backgroundColor: i === index ? "#111" : "#CCC",
                                cursor: "pointer"
                            }}
                        />
                    ))}
                </div>
            </div>
        )
    }
}
```

This gives you full one-at-a-time slide behavior, arrow navigation, and clickable dot indicators, with the crossfade-and-slide transition configurable through the `transition` and initial/exit values.

### Adding autoplay

```tsx
import { useEffect } from "react"

// Inside the same component, after index/setIndex are defined:
useEffect(() => {
    const timer = setInterval(next, 5000)
    return () => clearInterval(timer)
}, [index])
```

Pause this on hover by tracking a `hovered` state and skipping the interval when true, so visitors reading testimonial content don't have it change out from under them mid-read.

---

## Option 3: CMS-connected carousel with Gallery Kit

For a carousel that pulls directly from a CMS collection, so adding a new testimonial, product, or image automatically extends the carousel without manually adding slides, [Gallery Kit](/plugins/gallery-kit) includes a carousel layout built for exactly this.

**What it adds over a custom build:** direct CMS collection connection, so content updates don't require touching the carousel's code or layers at all, plus navigation dots, arrows, swipe support, and autoplay configuration, all set up visually from Framer's property panel rather than written by hand.

**Setup:**

1. Install [Gallery Kit](/plugins/gallery-kit) from the FramerHub plugin page or Framer Marketplace.
2. Add the carousel component and connect it to your CMS collection (testimonials, products, images, whatever fits your use case).
3. Configure autoplay, navigation style, and transition behavior from the property panel.
4. Preview and test swipe behavior specifically on a real mobile device.

---

## Choosing the right approach for your use case

**Simple image or logo row, free-scrolling is fine:** native horizontal Scroll component.

**Need precise one-at-a-time slides with dots and arrows, content isn't CMS-driven:** a custom code override gives full control without plugin dependency.

**CMS-connected content (testimonials, products, a growing image set):** [Gallery Kit](/plugins/gallery-kit)'s carousel layout, so new CMS entries extend the carousel automatically.

---

## Quick comparison of the three approaches

<table>
<thead>
  <tr>
    <th>
      
    </th>
    
    <th>
      Native Scroll
    </th>
    
    <th>
      Custom code override
    </th>
    
    <th>
      Gallery Kit carousel
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Setup effort
    </td>
    
    <td>
      Lowest
    </td>
    
    <td>
      Highest
    </td>
    
    <td>
      Low
    </td>
  </tr>
  
  <tr>
    <td>
      Navigation dots/arrows
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Yes (build yourself)
    </td>
    
    <td>
      Yes (built in)
    </td>
  </tr>
  
  <tr>
    <td>
      Snap-to-slide
    </td>
    
    <td>
      No (free scroll)
    </td>
    
    <td>
      Yes
    </td>
    
    <td>
      Yes
    </td>
  </tr>
  
  <tr>
    <td>
      Autoplay
    </td>
    
    <td>
      No
    </td>
    
    <td>
      Yes (build yourself)
    </td>
    
    <td>
      Yes (configurable)
    </td>
  </tr>
  
  <tr>
    <td>
      CMS-connected
    </td>
    
    <td>
      Manual (via Collection List)
    </td>
    
    <td>
      Manual (map data yourself)
    </td>
    
    <td>
      Yes (native)
    </td>
  </tr>
  
  <tr>
    <td>
      Ongoing maintenance
    </td>
    
    <td>
      None
    </td>
    
    <td>
      Yours
    </td>
    
    <td>
      Plugin-maintained
    </td>
  </tr>
</tbody>
</table>

Pick based on how much control you need versus how much you want to build and maintain yourself. Most projects that need more than a basic swipeable row are better served by a CMS-connected plugin than a fully custom build, unless the design requires something genuinely bespoke that a general-purpose carousel component can't express.

---

## Design considerations specific to carousels

**Don't rely on a carousel for content that must be seen.** Studies on hero carousels consistently show that content beyond the first slide gets seen by a small fraction of visitors. If something is truly important, don't bury it in slide two or three.

**Autoplay carefully, or not at all, for readable content.** A testimonial carousel that auto-advances before a visitor finishes reading works against you. Use a generous interval (5+ seconds) and pause on hover/focus, or skip autoplay entirely for text-heavy slides.

**Make navigation obvious.** Dots alone are subtle. Pairing dots with visible arrow controls, especially on desktop where hover affordance exists, makes the interaction more discoverable for visitors who don't think to swipe.

**Consider touch target size on mobile.** Arrow buttons and dot indicators need to be large enough to tap reliably, not so small or close together that visitors miss-tap between them.

---

## Performance considerations for carousels

**Lazy-load images beyond the first slide or two.** A carousel with ten high-resolution images doesn't need all ten loaded immediately; loading the visible slide plus the next one or two, and deferring the rest, keeps initial page load fast.

**Prefer transform-based sliding over animating layout properties.** Sliding a carousel by animating `x`/`translateX` stays on the compositor and performs better than animating `left` or `margin`, especially on lower-powered mobile devices.

**Avoid too many simultaneous autoplaying carousels on one page.** Multiple independently-animating carousels running at once adds up in terms of both visual noise and actual rendering cost. If a page has several, consider whether all of them truly need autoplay.

---

## Carousel patterns by use case

**Hero/banner carousel.** Full-width, usually 2-4 slides, often autoplaying with a long interval. Keep critical messaging on the first slide, since not every visitor will see the rest.

**Product carousel.** Typically shows several products at once (not one full-width slide), with clear pricing and a consistent card layout. CMS-connected so new products appear automatically. Snap-to-item behavior (rather than free scroll) usually looks more intentional for commerce contexts.

**Testimonial carousel.** Usually one testimonial at a time, larger text, no aggressive autoplay given the reading time required. Dot navigation plus arrows work well here since testimonials are often revisited or compared rather than browsed quickly.

**Logo strip / social proof carousel.** Small, decorative, often continuously auto-scrolling at a slow, steady pace rather than discrete slide-by-slide advancement. This is one of the few cases where fast, continuous autoplay is usually appropriate, since the content is passive and not meant to be individually read.

**Image gallery carousel.** Often paired with a lightbox, clicking a carousel image opens a full-screen view rather than the carousel itself being the primary viewing experience.

---

## Common carousel mistakes

**Too many slides in a hero carousel.** Beyond 3-4 slides, engagement with later slides drops sharply. If you have more content than that, a different layout (a grid, a separate page) usually serves it better than burying it deep in a carousel.

**No pause-on-hover for autoplay.** An autoplaying carousel that keeps moving while a visitor is actively trying to read or interact with it is a common source of frustration. Pause on hover and on keyboard focus.

**Inconsistent slide sizing.** If slides vary significantly in height or width without a deliberate design reason, the carousel can visually jump or shift awkwardly as it transitions. Keep dimensions consistent unless variation is an intentional part of the design.

**Treating a carousel as a substitute for real information architecture.** Cramming everything into a single carousel because it's easier than restructuring a page's content usually produces a worse experience than a well-organized static layout with sections.

---

## Accessibility for carousels

**Keyboard navigation.** Arrow keys should move between slides when the carousel has focus, not just mouse clicks and touch swipes.

**Pause control for autoplay.** Any auto-advancing carousel should have a visible pause control, since continuously moving content can be genuinely disruptive for some visitors, beyond just being annoying.

**Meaningful alt text and labels.** Navigation buttons need accessible labels ("Next slide," "Previous slide"), not just an unlabeled icon, for screen reader users.

For the broader component ecosystem beyond carousels specifically, [FramerHub Components](/components) and the [Components plugin](/plugins/framer-components) cover 90+ common interactive patterns, restylable from Framer's native panel. For structuring CMS collections that feed a carousel or slider, see the [Framer CMS complete guide](/blog/framer-cms-complete-guide).

---

## FAQ

### Does Framer have a built-in carousel component?

Not a dedicated carousel component with dots, arrows, and autoplay built in. Framer's Scroll component set to horizontal direction can function as a basic swipeable slider, but features like navigation dots, arrow controls, autoplay, and CMS-connected carousel behavior require either custom code or a dedicated carousel plugin.

### How do I make a testimonial carousel in Framer?

Connect a Collection List (with testimonial content as CMS fields) to a horizontal Scroll component for a basic version, or use a carousel component built for CMS content, which typically adds navigation dots, arrows, and autoplay on top of the same CMS-connected structure.

### What's the difference between a carousel and a slider?

The terms are often used interchangeably. Some designers use "slider" for a single large hero image or banner that transitions between a few full-width slides, and "carousel" for a row of smaller items (products, testimonials, cards) that scroll or advance together. The underlying interaction pattern is similar either way.

### Should a carousel autoplay?

Autoplay works for passive, decorative content like a logo strip or background banner, but for content visitors need to actually read (testimonials, product details), autoplay that advances before someone finishes reading can hurt more than help. If you autoplay, use a generous interval and pause on hover or interaction.

### Is Gallery Kit's carousel connected to Framer's CMS?

Yes. [Gallery Kit](/plugins/gallery-kit)'s carousel layout connects directly to a CMS collection, so adding, removing, or reordering items in the collection updates the carousel automatically without manually rebuilding slides.

---

## Bottom line

A **framer carousel** can be as simple as a native horizontal Scroll component or as involved as a custom-coded, snap-to-slide carousel with autoplay and dot navigation. For anything CMS-driven, testimonials, products, a growing image set, [Gallery Kit](/plugins/gallery-kit) covers the carousel pattern without writing or maintaining the code yourself.

*Last updated: September 2026*
