---
title: "Testimonial slider: HTML & CSS, no JavaScript — Testymo"
description: "A testimonial slider in plain HTML and CSS. Copy the code, watch it snap and swipe in the live preview, and skip the carousel library — scroll-snap replaced it."
url: https://testymo.com/free/testimonial-slider
---

[Free tools](https://testymo.com/free) ★ Testimonial slider

# Testimonial slider in HTML and CSS

Six quotes on a track that stops cleanly on one card at a time — swipe it on a phone, tab into it and arrow across on a desktop. It is a flex row and three CSS properties, and the code below is the code running above it.

A testimonial slider is a horizontal, scrollable row of customer quotes that snaps to one card at a time instead of stacking them down the page. This page hands you a working one as plain HTML and CSS, for freelancers, agencies and small business owners who edit their own site and would rather not add a carousel library to move a row sideways.

- **What it costs** — Nothing. No account, no email, no watermark, no limit on how often you use it.
- **Where your text goes** — Nowhere. The whole tool runs in your browser — nothing you type is sent, stored, or seen by us. The page-view measurement this site carries counts the visit, never the text.

Live preview — drag it, or tab into it and press the arrow keys

Sample quotes written for the demo — no customer wrote them.

The whole slider — HTML and CSS, one block

4.1 KB · no JavaScript

```
<!-- Testimonial slider — generated free at testymo.com/free/testimonial-html-generator -->
<section class="tm-testimonials">
  <style>
  .tm-testimonials { font: inherit; }
  .tm-list { display: flex; gap: 20px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-left: 6px; padding: 6px 6px 18px; }
  .tm-card { flex: 0 0 min(78vw, 340px); scroll-snap-align: start; margin: 0; }
  .tm-card { background: #ffffff; border-radius: 8px; padding: 22px 24px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.09); }
  .tm-stars { margin: 0; color: #1233d4; letter-spacing: 3px; }
  .tm-quote { margin: 10px 0 16px; line-height: 1.55; }
  .tm-who { display: flex; align-items: center; gap: 10px; }
  .tm-avatar { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; background: #1233d4; color: #ffffff; font-size: 0.8em; font-weight: 700; }
  .tm-name { display: block; font-weight: 700; }
  .tm-role { display: block; font-size: 0.85em; opacity: 0.72; }
  </style>
  <div class="tm-list" tabindex="0" role="region" aria-label="Customer testimonials">
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 5 out of 5 stars">★★★★★</p>
      <blockquote class="tm-quote">They rebuilt our checkout in a week and conversions doubled. I keep waiting for the catch.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">JP</span>
        <span>
          <span class="tm-name">June Park</span>
          <span class="tm-role">COO, Fernwell</span>
        </span>
      </figcaption>
    </figure>
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 5 out of 5 stars">★★★★★</p>
      <blockquote class="tm-quote">Signed for a month. Stayed three years. Make of that what you will.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">IS</span>
        <span>
          <span class="tm-name">Ivy Sandoval</span>
          <span class="tm-role">CEO, Northbank</span>
        </span>
      </figcaption>
    </figure>
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 3 out of 5 stars">★★★☆☆</p>
      <blockquote class="tm-quote">Good work overall, though the kickoff ran long and I would have liked the first draft a week earlier.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">RH</span>
        <span>
          <span class="tm-name">Reuben Hale</span>
          <span class="tm-role">Product Manager, Cobbler</span>
        </span>
      </figcaption>
    </figure>
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 5 out of 5 stars">★★★★★</p>
      <blockquote class="tm-quote">I have already sent three friends. That is not a review, that is a confession.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">BL</span>
        <span>
          <span class="tm-name">Bea Lindqvist</span>
          <span class="tm-role">Illustrator, Freelance</span>
        </span>
      </figcaption>
    </figure>
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 5 out of 5 stars">★★★★★</p>
      <blockquote class="tm-quote">Nobody has ever complimented our checkout before. Two people did this month, unprompted, in the form.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">IF</span>
        <span>
          <span class="tm-name">Isabel Ferreira</span>
          <span class="tm-role">Ecommerce, Two Rivers</span>
        </span>
      </figcaption>
    </figure>
    <figure class="tm-card">
      <p class="tm-stars" role="img" aria-label="Rated 5 out of 5 stars">★★★★★</p>
      <blockquote class="tm-quote">Worth every penny, twice over.</blockquote>
      <figcaption class="tm-who">
        <span class="tm-avatar" aria-hidden="true">LN</span>
        <span>
          <span class="tm-name">Lena Novak</span>
          <span class="tm-role">Owner, Studio Novak</span>
        </span>
      </figcaption>
    </figure>
  </div>
</section>
```

## 01 The slider is three properties

Everything that makes the track above slide, snap and stay put is in these four lines. There is no other file, no build step and no script — this is the complete mechanism:

```
.tm-list { display: flex; gap: 20px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-left: 6px; padding: 6px 6px 18px; }
.tm-card { flex: 0 0 min(78vw, 340px); scroll-snap-align: start; margin: 0; }
```

`overflow-x: auto` makes the row scrollable. `scroll-snap-type: x mandatory` tells the browser it must come to rest on a snap point rather than wherever the finger left it, and `scroll-snap-align: start` on each card says the left edge is that point. The browser does the physics: momentum, rubber-banding, the deceleration curve, all of it native and all of it already tuned for the device it is running on.

Two numbers are doing quieter work. `flex: 0 0 min(78vw, 340px)` caps a card at 340px on a desktop but makes it 78% of the viewport on a phone — **the leftover 22% is the affordance**, because a sliver of the next card is the only thing telling a thumb there is more to the right. And the 6px of `scroll-padding-left` matches the track’s own 6px of padding, so a snapped card stops just inside the edge instead of flush against it; the 18px at the bottom is there so a card’s shadow is not clipped by the scroll container it lives in.

## 02 When a slider is the right shape, and when it costs you

A slider trades vertical space for horizontal space, and that trade is good in exactly one situation: **you have more quotes than the page has room for, and the quotes are supporting evidence rather than the argument itself.** A rail under a hero, a strip below a feature block, a phone-first page where swiping is the natural gesture — all good.

Three cases where it is the wrong pattern, and one myth:

- **Two or three testimonials.** The track never overflows, so nothing scrolls and nothing snaps; on a desktop you have built [a grid](https://testymo.com/free/testimonial-section-html) with extra steps, and one that left-aligns awkwardly in a wide column.
- **The quotes are the argument.** Everything past the first card is optional reading, and readers treat optional reading as optional. If the third testimonial is the one that answers the objection blocking the sale, do not put it behind a swipe.
- **One quote you want people to actually read.** That is [a single card](https://testymo.com/free/testimonial-card-html) on a readable measure, not a track with one thing on it.

The myth: that a slider hides quotes from search engines. It does not. Every card is in the HTML, fully rendered, with no lazily-inserted slides — a crawler and a screen reader both get all six. What a slider costs is *human* attention, which is a design question, not an indexing one. Plenty of advice online gets those two backwards.

## 03 Best on a phone. On a keyboard it needs one attribute.

This is the one testimonial pattern that gets *better* on a small screen. A grid has to collapse to a single column and a card just gets narrower, but a slider on a phone is doing the thing phones are best at: native, momentum-scrolled, one-thumb horizontal swiping, with the browser’s own scroll physics rather than a script’s imitation of them.

A keyboard is where it needs help, and it is a single attribute. The track carries `tabindex="0"` so it can take focus, plus `role="region"` and an `aria-label` so it announces itself as something rather than as an unnamed box. With focus on the track, the arrow keys scroll it. Without `tabindex`, a keyboard user in some browsers simply cannot reach the second quote — which is the single most common defect in hand-rolled sliders, including most of the ones you will find on CodePen.

Two more things this pattern gets right by having no script. There is no autoplay, so nothing ever moves a quote out from under someone reading it — an autoplaying carousel needs a visible pause control to be usable, and almost none of them ship one. And there is no animation to suppress under `prefers-reduced-motion`, because every movement here is a scroll the reader started.

## 04 What the carousel library was actually for

Search for a testimonial slider and you are handed Swiper, Slick, Owl, an Elementor widget or a framework component. Those are not frauds — they give you real things this snippet does not have: **previous and next arrows, pagination dots, autoplay, an infinite loop, and a different number of visible slides per breakpoint.** If you need an infinite autoplaying loop, use one.

The honest accounting is what you pay for them. A carousel library is a dependency you now own: a runtime that has to download, parse and boot before the first card can move; a version to keep current; and a failure mode where the script is blocked or errors and the markup collapses into a stack of unstyled slides with every quote visible at once. The whole slider on this page is **4.1 KB** of HTML and CSS, and that figure is the entire dependency list.

If you want arrows badly enough, the markup above is plain enough to wire up yourself: two buttons calling `scrollBy()` on the track, with real text inside them so they have accessible names. That stays your choice rather than a thing that arrived with a library — and it is why the snippet ships without them.

## 05 Layout shift: this one does not move the page

Sliders are a common source of the jump you feel when a page finishes loading, and it is worth knowing why this one is not. Three reasons, and each is a property of the code rather than luck:

- **Card width is fixed before anything loads.** `flex: 0 0 min(78vw, 340px)` is resolvable at first paint, so the track takes its final height from the tallest card immediately. A library that measures the container and then sets widths cannot do that.
- **There are no images.** The avatar is a circle of initials generated from the name, so there is no file to arrive late at an unreserved size.
- **No webfont of its own.** The snippet sets `font: inherit`, so it uses whatever your page already loaded — it never adds a second font swap on top of yours.

The classic carousel shift comes from cloning slides for the infinite loop and applying transforms after hydration: the section is one height on first paint and another a moment later, and everything below it moves. Nothing here runs after first paint, because nothing here runs.

## 06 Make it yours, or stop re-pasting it

The colours, corner radius, card look and the quotes themselves are all editable in [the testimonial HTML generator](https://testymo.com/free/testimonial-html-generator), which emits this exact snippet from your own text and five card designs. The two sibling patterns are [a responsive testimonial section](https://testymo.com/free/testimonial-section-html) when you want every quote read rather than swiped past, and [a single testimonial card](https://testymo.com/free/testimonial-card-html) when one quote is doing all the work. If your site already runs Tailwind, the same track is [three utility classes and one everybody forgets](https://testymo.com/free/testimonial-tailwind#slider). Where on a page to put any of them is worked through in [social proof sections](https://testymo.com/social-proof-examples).

The thing hand-written HTML costs you arrives with the next testimonial: every new quote is an edit to your site’s code, and the section quietly stops being maintained the month things get busy. That is the line where [a live widget](https://testymo.com/examples) earns its script tag — approve a quote and it is on the page at the next load, with nothing to re-paste. For a handful of quotes that will not change for a year, paste the block above and forget it.

## 07 Questions this page gets

- **How do I show two or three cards at a time instead of one?** — Change the width in `flex: 0 0 min(78vw, 340px)` — there is no slide count to configure, because there are no slides. Cards are just flex items, so `min(45vw, 300px)` shows about two and `min(30vw, 260px)` about three, at every screen size, with no breakpoints to write.
- **Will it work in Squarespace, Wix, Webflow or WordPress?** — Yes, anywhere there is a custom-HTML box: the CSS travels inside the block, so there is no stylesheet to upload and nothing to enqueue. Because the output holds no JavaScript it also survives the site-builder plans that strip scripts. [The integrations pages](https://testymo.com/integrations) show where that box lives on each platform.
- **Can I add arrows or make it autoplay?** — Not without JavaScript, and the snippet is deliberately script-free. Arrows are a few lines of your own calling `scrollBy()` on the track. Autoplay is the one to think twice about: it moves a quote a reader is halfway through, and it needs a pause control to be usable at all.
- **Does it need a wrapper, a container class or a reset?** — No. It is one `<section>` with its own `<style>` inside it, and every class is prefixed `tm-` so nothing collides with your site. Drop it wherever the section should appear.
- **What is the comment at the top of the code?** — A one-line pointer back to the generator, so you can find it again to change the colours or the quotes. Delete it freely — the code is yours without conditions.
- **Can I use these sample testimonials?** — No — they are invented for the demo and nobody said them. Replace every one with words a real customer wrote and agreed you could publish. [Permission to use testimonials](https://testymo.com/blog/permission-to-use-testimonials) covers what to ask for and what to keep on file.

More free tools

- [Testimonial HTML generator I want to change the quotes and colors before I paste it.](https://testymo.com/free/testimonial-html-generator)
- [Testimonial section HTML How do I build a testimonials section that reflows on its own?](https://testymo.com/free/testimonial-section-html)
- [Testimonial card HTML How do I style one testimonial card properly?](https://testymo.com/free/testimonial-card-html)
- [Tailwind testimonials How do I build these with Tailwind classes instead of CSS?](https://testymo.com/free/testimonial-tailwind)
- [Testimonial request generator How do I actually word the ask?](https://testymo.com/free/testimonial-request-generator)
- [Testimonial question picker What should I actually ask my customers?](https://testymo.com/free/testimonial-question-picker)
- [Testimonial image generator How do I turn this quote into something postable?](https://testymo.com/free/testimonial-image-generator)
- [Google review link generator How do I send someone straight to my Google review box?](https://testymo.com/free/google-review-link-generator)
- [Star rating calculator What's my average rating — and how many 5-star reviews until it moves?](https://testymo.com/free/star-rating-calculator)
- [Star rating HTML generator How do I show my star rating on my site — as code or an image?](https://testymo.com/free/star-rating-html-generator)
- [Review schema generator How do I mark up the testimonials on my page so Google can read them?](https://testymo.com/free/review-schema-generator)

The part no tool does

A tool can shape what you already have. Testymo is for getting it: a testimonial form people actually finish, your approval on every word before it goes public, and the permission recorded alongside it. Free to start — no card, no view meters.

[Collect your first testimonial →](https://testymo.com/app)
