03 / 22
All 22 in 22 Tailwind CSS Image Carousel
- 01Tailwind E-commerce Product Gallery Carousel with Thumbnails
- 02Tailwind Shop the Look Multi-Item Card Slider with Scroll Snap
- 03Tailwind Infinite Logo Scroller Marquee with No JavaScript
- 04Tailwind Product Colour Variant Picker Slider
- 05Tailwind Full-Screen Hero Slideshow with Auto Cross-Fade
- 06Tailwind Testimonial Card Carousel with Star Ratings
- 07Tailwind Meet the Team Profile Slider with Circular Portraits
- 08Tailwind Portfolio Gallery Slider with Hover Caption Reveal
- 09Tailwind Netflix-Style Content Row Carousel with Hover Expand
- 10Tailwind Magazine Split-Screen Article Slider
- 11Tailwind Onboarding Slider with Native CSS Scroll-Marker Dots
- 12Tailwind Vertical Image Carousel with Y-Axis Scroll Snap
- 13Tailwind 3D Coverflow Carousel with Perspective Transforms
- 14Tailwind Cross-Fade Image Slideshow with Manual Controls
- 15Tailwind Dual Opposite-Direction Marquee Slider
- 16Tailwind Dot Pagination Carousel with Target and Has Selectors
- 17Tailwind Prev / Next Arrow Carousel with Native Scroll Buttons
- 18Tailwind Before / After Image Comparison Slider
- 19Tailwind Accordion Expanding Image Panel Carousel
- 20Tailwind Autoplay Slider with Keyframe Track and Progress Bars
- 21Tailwind Zoom-on-Hover Image Gallery Slider
- 22Tailwind Parallax Text-Over-Image Story Slider
Tailwind Infinite Logo Scroller Marquee with No JavaScript
A seamless, endlessly looping strip of partner logos — the 'trusted by' band on almost every SaaS landing page. The port's lesson: --animate-* in @theme mints animate-tcar03-scroll, so the animation becomes a design token like any colour.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcar-03 w-full min-h-svh flex flex-col items-center justify-center gap-6 bg-tcar03-bg font-tcar03-sans py-10" aria-label="Trusted by leading teams">
<p class="text-xs tracking-[0.16em] uppercase text-tcar03-mute m-0">Trusted by 4,000+ teams</p>
<div class="group w-[min(720px,100%)] overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
<ul class="list-none flex items-center gap-16 w-max m-0 p-0 animate-tcar03-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:flex-wrap motion-reduce:justify-center motion-reduce:w-auto motion-reduce:gap-x-12 motion-reduce:gap-y-8">
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
</ul>
</div>
</section><section class="tcar-03 w-full min-h-svh flex flex-col items-center justify-center gap-6 bg-tcar03-bg font-tcar03-sans py-10" aria-label="Trusted by leading teams">
<p class="text-xs tracking-[0.16em] uppercase text-tcar03-mute m-0">Trusted by 4,000+ teams</p>
<div class="group w-[min(720px,100%)] overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
<ul class="list-none flex items-center gap-16 w-max m-0 p-0 animate-tcar03-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:flex-wrap motion-reduce:justify-center motion-reduce:w-auto motion-reduce:gap-x-12 motion-reduce:gap-y-8">
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
</ul>
</div>
</section>@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Newsreader:opsz,wght@6..72,500;6..72,700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Newsreader:opsz,wght@6..72,500;6..72,700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
--animate-tcar03-scrollin@themeis the whole reason this port is worth reading: an animation becomes a named design token with a generated utility, exactly like a colour.animation-play-stateis the one property here with no utility and no plausible future one — it is a state, not a scale. The arbitrary property on agroup-hover:variant is idiomatic, not a workaround.- UI change from the CSS original: the reduced-motion fallback now sets an explicit
gap-x-12 gap-y-8wrapped grid rather than inheriting the 64px marquee gap, so the static version reads as a deliberate logo grid instead of a broken strip.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Infinite Logo Scroller Marquee with No JavaScript
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-infinite-logo-scroller-marquee-no-javascript/
A seamless, endlessly looping strip of partner logos — the 'trusted by' band on almost every SaaS landing page. The port's lesson: --animate-* in @theme mints animate-tcar03-scroll, so the animation becomes a design token like any colour.
## HTML
```html
<section class="tcar-03 w-full min-h-svh flex flex-col items-center justify-center gap-6 bg-tcar03-bg font-tcar03-sans py-10" aria-label="Trusted by leading teams">
<p class="text-xs tracking-[0.16em] uppercase text-tcar03-mute m-0">Trusted by 4,000+ teams</p>
<div class="group w-[min(720px,100%)] overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
<ul class="list-none flex items-center gap-16 w-max m-0 p-0 animate-tcar03-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:flex-wrap motion-reduce:justify-center motion-reduce:w-auto motion-reduce:gap-x-12 motion-reduce:gap-y-8">
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Infinite Logo Scroller Marquee with No JavaScript
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-infinite-logo-scroller-marquee-no-javascript/
A seamless, endlessly looping strip of partner logos — the 'trusted by' band on almost every SaaS landing page. The port's lesson: --animate-* in @theme mints animate-tcar03-scroll, so the animation becomes a design token like any colour.
## HTML
```html
<section class="tcar-03 w-full min-h-svh flex flex-col items-center justify-center gap-6 bg-tcar03-bg font-tcar03-sans py-10" aria-label="Trusted by leading teams">
<p class="text-xs tracking-[0.16em] uppercase text-tcar03-mute m-0">Trusted by 4,000+ teams</p>
<div class="group w-[min(720px,100%)] overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
<ul class="list-none flex items-center gap-16 w-max m-0 p-0 animate-tcar03-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:flex-wrap motion-reduce:justify-center motion-reduce:w-auto motion-reduce:gap-x-12 motion-reduce:gap-y-8">
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">NORTHWIND</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Lumen&Co</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">ARCADIA</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Föhn</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">Kestrel</li>
<li aria-hidden="true" class="flex-none text-[22px] font-bold tracking-[0.02em] text-tcar03-logo whitespace-nowrap font-tcar03-serif opacity-75">MONOLITH</li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar03-bg: #f6f7f9;
--color-tcar03-bg: oklch(0.97 0.003 255);
--color-tcar03-mute: #8a93a3;
--color-tcar03-mute: oklch(0.65 0.02 255);
--color-tcar03-logo: #3e4654;
--color-tcar03-logo: oklch(0.42 0.02 255);
--font-tcar03-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tcar03-serif: 'Newsreader', Georgia, serif;
--animate-tcar03-scroll: tcar03-scroll 24s linear infinite;
}
/* Keyframes have no utility form and never will. */
@keyframes tcar03-scroll {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-03 {
width: 100%;
min-height: 100svh;
}
.tcar-03 ::selection {
background: #111827;
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar-03 .group {
-webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
```How this works
The animation is a token. Tailwind v4's --animate-* namespace turns an @theme entry into a utility, so the marquee reads animate-tcar03-scroll and the timing lives with the colours rather than in an anonymous rule at the bottom of the sheet. The @keyframes block itself stays CSS — there is no utility form for a keyframe, and there should not be.
The two-copy contract is markup, not style. The track holds the list twice; the keyframe ends at exactly -50%, so the reset is invisible. The duplicate half carries aria-hidden="true", so every logo is announced once.
Pause is a variant on the group. group-hover:[animation-play-state:paused] and its group-focus-within: twin let a user stop the strip to read a name — the same two states the CSS version wrote as a selector list.
Make it yours
- Speed: the
24sin--animate-tcar03-scroll. Longer is slower. - Direction: add a second
@themeentry ending inreverse, or flip the keyframe endpoints. - Fade width: the
12%/88%stops in the mask. - Spacing: the track's
gap-16.
Gotchas — read before shipping
- Exactly two identical halves, and the keyframe must end at
-50%. Three copies, or-100%, and the loop visibly jumps. aria-hidden="true"on the duplicated set is not optional — without it a screen reader reads the whole client list twice.animation-play-statehas no utility; the arbitrary property is the answer, and it must sit on the animated element, not the hovered one — hence thegroup.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
CSS animation is universal and mask-image is Baseline since Safari 15.4; the floor quoted is Tailwind v4's generated sheet. The -webkit-mask shim is included for older Safari.