Testimonial Carousel — Free HTML CSS JS Slider Snippet

Testimonial Carousel · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Transform-based sliding
A single translateX on a flex track gives GPU-accelerated 60fps transitions with no layout cost.
Autoplay that respects the reader
Advances every 5s but pauses on hover and keyboard focus, resuming when the user leaves.
Infinite wrap-around
Index normalisation with modulo means next past the end loops to the start and vice versa.
Data-driven slides
A DATA array builds slides, derives author initials, and renders the correct number of filled stars per rating.
Animated pill dots
The active dot transitions from a circle to a 24px pill for a clean progress indicator.
Single source of truth
Arrows, dots, and autoplay all call one goTo() function, so the slide, dots, and index never drift apart.
Star ratings
Renders 1–5 filled stars per testimonial so partial ratings display correctly.
Accessible markup
Roledescription, tab roles, and aria-labels make the carousel and its controls understandable to screen readers.

About this UI Snippet

Testimonial Carousel — Autoplay Slider with Stars, Avatars and Animated Dots

Screenshot of the Testimonial Carousel snippet rendered live

Social proof sells, but a wall of testimonials is overwhelming and a single static quote is forgettable. The testimonial carousel solves both problems: it shows one customer quote at a time, full and readable, then advances automatically so visitors see several without scrolling. This component is a complete, accessible carousel built with a CSS transform track, autoplay that pauses on interaction, arrow controls, and animated progress dots — all in plain HTML, CSS, and vanilla JavaScript with no slider library.

The transform-based track

The mechanics are a flex track inside an overflow: hidden viewport. Every slide has flex: 0 0 100%, so each one is exactly the viewport's width and they line up in a horizontal row. Sliding is a single transform: translateX(-N%) on the track, where N is the active index times 100 — moving to slide 2 translates the track by -100%, slide 3 by -200%, and so on. Because it animates only transform, the slide runs on the GPU compositor at 60fps with no layout work, and will-change: transform hints the browser to promote the track to its own layer ahead of time.

Data-driven slides and ratings

The carousel is built from a DATA array of { text, name, role, rating, color } objects. On load the script loops the array, builds each slide's markup, and derives two things automatically: the author's initials (by splitting the name and taking each word's first letter) for the gradient avatar, and the star row (by rendering a filled star SVG for each point up to rating out of five). This means adding a testimonial is a single array entry — no markup edits — and the four-star example shows partial ratings render correctly.

Autoplay with pause-on-interaction

A setInterval advances the carousel every 5 seconds by calling goTo(index + 1). The crucial UX detail is that autoplay yields to the user: mouseenter and focusin clear the interval so the carousel stops while someone is reading or tabbing through it, and mouseleave and focusout restart it. Every manual action — clicking an arrow or a dot — also calls restart(), which clears and re-creates the timer so the full 5 seconds is given to the slide the user just chose rather than whatever was left on the previous tick.

Infinite wrap-around

The goTo() function normalises any index with (i + length) % length, so advancing past the last slide wraps to the first and going back from the first wraps to the last. The arrows and autoplay all route through this one function, which means there is a single source of truth for the current index, the track transform, and the active dot — no chance of the dots drifting out of sync with the visible slide.

Animated progress dots

The dots are real <button> elements with role="tab". The active dot is not just a different colour — it stretches from a circle to a pill with width: 24px via a CSS transition on width, giving a subtle, modern progress indicator. Clicking any dot jumps straight to that slide and restarts autoplay. The arrows are circular icon buttons with hover states that adopt the accent colour, and everything carries appropriate aria-label and aria-roledescription attributes so the carousel is understandable to screen readers.

Customisation

To use it, replace the DATA array with your real testimonials — set each rating from 1 to 5, give each author a gradient color, and the avatars and stars render automatically. Adjust the 5000ms autoplay interval, change the 0.5s slide transition duration or easing, and swap the #6366f1 accent (active dot, arrow hover, avatars) for your brand. To show real photos instead of initials, render an <img> in place of the .tc-avatar span. For a multi-card view, change the slide's flex-basis to 50% or 33.33% and step the transform by that amount.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to work out the modulo wrap-around math by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why goTo computes the index as (i plus DATA.length) modulo DATA.length instead of a simple bounds check, and why every navigation path — arrows, dots, and autoplay — funnels through that single function rather than each setting the transform independently. The same assistant can help optimize it — for instance whether pausing on mouseenter/focusin but not on touch interactions leaves a gap on mobile, or whether rebuilding all slides' innerHTML up front instead of lazily is wasteful for a very large testimonial set. It's also useful for extending the carousel: ask it to show two testimonials per view on wide screens, add swipe gesture support for touch devices, or sync the dots with a progress-bar countdown showing time until the next auto-advance. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an autoplaying "testimonial carousel" in plain HTML, CSS, and JavaScript using a single transform-driven track — no slider library, no framework.

Requirements:
- A viewport with overflow hidden containing a flex track, where every slide has flex: 0 0 100% so slides sit side by side each exactly the viewport's width.
- A single goTo(index) function that normalizes any given index with modulo arithmetic so it wraps correctly in both directions (going past the last slide returns to the first, going before the first wraps to the last), sets the track's transform to translateX of negative index times 100%, and updates which dot indicator is marked active — every other piece of navigation logic (arrows, dots, autoplay) must call this one function rather than duplicating the transform/active-dot logic.
- Build slides and dot indicators dynamically from a single data array of testimonial objects (quote text, name, role, star rating, accent color), deriving each avatar's initials automatically from the name and rendering exactly as many filled stars as the rating value out of five.
- An autoplay timer that advances to the next slide automatically on a fixed interval, where every manual navigation (arrow click or dot click) clears and restarts that timer so the newly selected slide gets the full interval before it advances again.
- Autoplay must pause while the pointer hovers over the carousel or while any element inside it has keyboard focus, and resume when the pointer leaves or focus moves away.
- The active dot indicator must visually grow from a small circle into a wider pill shape via a CSS transition, distinct from the inactive dots.
- Include appropriate ARIA roles and labels (carousel role description, tab roles on the dots, labeled prev/next buttons) so the carousel is understandable via screen reader and keyboard.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste the HTML, CSS, and JSA testimonial card renders with a star rating, quote, author, arrow controls, and a row of dots; it begins autoplaying every 5 seconds.
  2. 2
    Use the arrowsClick the left/right arrows to move between testimonials; the track slides smoothly and autoplay timing resets.
  3. 3
    Click a dotJump directly to any testimonial; the active dot stretches into a pill to mark your position.
  4. 4
    Hover to pauseMove the pointer over the carousel (or tab into it) and autoplay pauses so you can read; it resumes when you leave.
  5. 5
    Replace the testimonialsEdit the DATA array — each entry's rating drives the stars and the name drives the avatar initials automatically.
  6. 6
    Theme and time itSwap the #6366f1 accent and adjust the 5000ms interval and 0.5s slide duration to fit your brand and pace.

Real-world uses

Common Use Cases

Landing-page social proof
Rotate customer quotes near your CTA to build trust without a long testimonials wall — pair with a logo cloud of customer brands.
Product and SaaS marketing
Showcase reviews from different roles (CTO, PM, founder) so each visitor sees someone like them; complements a pricing card section.
Agency and freelance portfolios
Cycle through client praise to reinforce credibility alongside your work; for a single highlighted quote use a testimonial card.
App store and review highlights
Surface your best star-rated reviews; show the full distribution with a rating breakdown.
Course and creator pages
Rotate student or subscriber testimonials to convert visitors on the fence.
Learning carousel mechanics
A reference for transform tracks, autoplay with pause-on-interaction, and synced dot indicators.

Got questions?

Frequently Asked Questions

The interval is set in restart() as setInterval(..., 5000) — change 5000 to your preferred milliseconds. To disable autoplay entirely, remove the restart() call at the bottom and the mouseenter/leave/focus handlers, leaving only the arrows and dots for manual control. The slide animation speed is separate: edit the 0.5s transition on .tc-track.

Change the slide's flex-basis from 100% to 50% (two up) or 33.33% (three up) in .tc-slide, and update goTo() to translate by index * (100 / perView) percent. You may also want the dots to represent pages rather than individual slides. The autoplay, wrap-around, and pause logic stay the same.

Every manual navigation calls restart(), which clears and recreates the timer. This gives the slide you just selected the full interval before it advances, rather than the leftover fraction of the previous tick — so the carousel never jumps away a moment after you click. It is a small detail that makes manual control feel responsive.

Replace the <span class="tc-avatar">initials</span> in the slide template with <img class="tc-avatar" src={t.img} alt={t.name}> and add object-fit: cover to the .tc-avatar rule so the photo fills the circle. Add an img field to each DATA entry. Keep the initials version as a fallback for testimonials without a photo.

Keep the index in state and bind the track's transform to translateX(-index*100%). Render DATA with .map/v-for/*ngFor. Run autoplay in an effect that sets an interval and clears it on cleanup (useEffect return, onUnmounted, ngOnDestroy) — this is essential to avoid leaked timers. Pause handlers map to onMouseEnter/onMouseLeave (and onFocus/onBlur) that clear and restart the interval; arrows and dots call your goTo(i) setter.