Testimonials
Scrolling wall of love
Two rows drifting in opposite directions
Two rows drifting in opposite directions
Create a scrolling testimonial wall with Tailwind CSS made of two horizontal rows that drift in opposite directions. Above them, a centred heading and a muted subline. Each row is an overflow-hidden container with edge mask fades holding a flex track of six compact quote cards, duplicated once for a seamless loop; the top row animates leftwards over forty seconds and the bottom row rightwards over fifty, both paused on hover and disabled entirely under a reduced-motion media query. Each card is a fixed-width bordered rounded-xl white tile with an avatar circle, a name and handle stacked, and two or three lines of quote text in relaxed grey. Define the keyframes in a small style block at the end, using a minus fifty percent translation so the duplicated half lines up exactly. <section class="overflow-hidden py-16">
<div class="mx-auto mb-12 max-w-xl px-6 text-center">
<h2 class="text-3xl font-semibold tracking-tight text-neutral-900">A wall of quiet enthusiasm</h2>
<p class="mt-3 text-neutral-500">Collected from support threads, conference hallways and one very long changelog comment.</p>
</div>
<div class="wall-mask overflow-hidden">
<div class="wall-left flex w-max gap-4">
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">DK</span><span><span class="block text-sm font-medium text-neutral-900">Dana Køhler</span><span class="block text-xs text-neutral-400">@dkohler</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Replaced 400 lines of glue code with one workflow. The diff was the best thing I shipped all month.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-amber-500 text-[11px] font-medium text-white">JP</span><span><span class="block text-sm font-medium text-neutral-900">Jules Park</span><span class="block text-xs text-neutral-400">@julespark</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Six months in and the bill has not surprised us once. Genuinely rare in this category.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-green-600 text-[11px] font-medium text-white">MO</span><span><span class="block text-sm font-medium text-neutral-900">Mira Osei</span><span class="block text-xs text-neutral-400">@miraosei</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Support sent a query plan on a Sunday. Then they fixed the docs that caused the confusion.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-blue-600 text-[11px] font-medium text-white">LR</span><span><span class="block text-sm font-medium text-neutral-900">Lena Rask</span><span class="block text-xs text-neutral-400">@lenarask</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">The auditor asked for evidence, I sent a link, and the meeting ended twenty minutes early.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-500 text-[11px] font-medium text-white">TS</span><span><span class="block text-sm font-medium text-neutral-900">Tom Silva</span><span class="block text-xs text-neutral-400">@tsilva</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">2.1 billion rows migrated over a weekend. Zero incidents and a very calm Slack channel.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">HB</span><span><span class="block text-sm font-medium text-neutral-900">Hana Brandt</span><span class="block text-xs text-neutral-400">@hbrandt</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Our dashboard went from eleven seconds to instant. I have stopped apologising in meetings.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">DK</span><span><span class="block text-sm font-medium text-neutral-900">Dana Køhler</span><span class="block text-xs text-neutral-400">@dkohler</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Replaced 400 lines of glue code with one workflow. The diff was the best thing I shipped all month.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-amber-500 text-[11px] font-medium text-white">JP</span><span><span class="block text-sm font-medium text-neutral-900">Jules Park</span><span class="block text-xs text-neutral-400">@julespark</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Six months in and the bill has not surprised us once. Genuinely rare in this category.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-green-600 text-[11px] font-medium text-white">MO</span><span><span class="block text-sm font-medium text-neutral-900">Mira Osei</span><span class="block text-xs text-neutral-400">@miraosei</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Support sent a query plan on a Sunday. Then they fixed the docs that caused the confusion.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-blue-600 text-[11px] font-medium text-white">LR</span><span><span class="block text-sm font-medium text-neutral-900">Lena Rask</span><span class="block text-xs text-neutral-400">@lenarask</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">The auditor asked for evidence, I sent a link, and the meeting ended twenty minutes early.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-500 text-[11px] font-medium text-white">TS</span><span><span class="block text-sm font-medium text-neutral-900">Tom Silva</span><span class="block text-xs text-neutral-400">@tsilva</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">2.1 billion rows migrated over a weekend. Zero incidents and a very calm Slack channel.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">HB</span><span><span class="block text-sm font-medium text-neutral-900">Hana Brandt</span><span class="block text-xs text-neutral-400">@hbrandt</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Our dashboard went from eleven seconds to instant. I have stopped apologising in meetings.</p>
</article>
</div>
</div>
<div class="wall-mask mt-4 overflow-hidden">
<div class="wall-right flex w-max gap-4">
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-amber-500 text-[11px] font-medium text-white">RG</span><span><span class="block text-sm font-medium text-neutral-900">Ravi Gopal</span><span class="block text-xs text-neutral-400">@ravigopal</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Onboarded three analysts and none of them asked me a single question. Highest praise available.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">EV</span><span><span class="block text-sm font-medium text-neutral-900">Elena Vasquez</span><span class="block text-xs text-neutral-400">@evasquez</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Four vendors trialled. This was the only one the team kept using once the trial expired.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-green-600 text-[11px] font-medium text-white">AT</span><span><span class="block text-sm font-medium text-neutral-900">Aiko Tan</span><span class="block text-xs text-neutral-400">@aikotan</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Month-end close went from a three-day slog to a job that runs while I am asleep.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-blue-600 text-[11px] font-medium text-white">PM</span><span><span class="block text-sm font-medium text-neutral-900">Priya Mahal</span><span class="block text-xs text-neutral-400">@pmahal</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Sixty-two depots live in a fortnight. The rollout plan was one page long.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-500 text-[11px] font-medium text-white">SN</span><span><span class="block text-sm font-medium text-neutral-900">Sofia Neri</span><span class="block text-xs text-neutral-400">@sofianeri</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">The error messages tell you what to do next. Somebody clearly cared about that.</p>
</article>
<article class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">KB</span><span><span class="block text-sm font-medium text-neutral-900">Karl Bergen</span><span class="block text-xs text-neutral-400">@kbergen</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">We deleted an internal tool and two cron jobs. That is the review.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-amber-500 text-[11px] font-medium text-white">RG</span><span><span class="block text-sm font-medium text-neutral-900">Ravi Gopal</span><span class="block text-xs text-neutral-400">@ravigopal</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Onboarded three analysts and none of them asked me a single question. Highest praise available.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">EV</span><span><span class="block text-sm font-medium text-neutral-900">Elena Vasquez</span><span class="block text-xs text-neutral-400">@evasquez</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Four vendors trialled. This was the only one the team kept using once the trial expired.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-green-600 text-[11px] font-medium text-white">AT</span><span><span class="block text-sm font-medium text-neutral-900">Aiko Tan</span><span class="block text-xs text-neutral-400">@aikotan</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Month-end close went from a three-day slog to a job that runs while I am asleep.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-blue-600 text-[11px] font-medium text-white">PM</span><span><span class="block text-sm font-medium text-neutral-900">Priya Mahal</span><span class="block text-xs text-neutral-400">@pmahal</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">Sixty-two depots live in a fortnight. The rollout plan was one page long.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-500 text-[11px] font-medium text-white">SN</span><span><span class="block text-sm font-medium text-neutral-900">Sofia Neri</span><span class="block text-xs text-neutral-400">@sofianeri</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">The error messages tell you what to do next. Somebody clearly cared about that.</p>
</article>
<article aria-hidden="true" class="w-80 shrink-0 rounded-xl border border-neutral-200 bg-white p-5">
<div class="flex items-center gap-2.5"><span class="grid h-9 w-9 place-items-center rounded-full bg-neutral-900 text-[11px] font-medium text-white">KB</span><span><span class="block text-sm font-medium text-neutral-900">Karl Bergen</span><span class="block text-xs text-neutral-400">@kbergen</span></span></div>
<p class="mt-3 text-sm leading-relaxed text-neutral-600">We deleted an internal tool and two cron jobs. That is the review.</p>
</article>
</div>
</div>
</section>
<style>
/* Each track holds two identical halves, so -50% lands on an exact repeat. */
@keyframes wallLeft { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes wallRight { from { transform: translateX(-50%); } to { transform: translateX(0); } }
.wall-left { animation: wallLeft 40s linear infinite; }
.wall-right { animation: wallRight 50s linear infinite; }
.wall-mask:hover .wall-left, .wall-mask:hover .wall-right { animation-play-state: paused; }
.wall-mask { -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); }
@media (prefers-reduced-motion: reduce) { .wall-left, .wall-right { animation: none; } }
</style>