15 / 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 Dual Opposite-Direction Marquee Slider
Two image tracks gliding in opposite directions — the top row drifts left while the bottom drifts right. One keyframe, two @theme animation tokens, and the second one differs from the first by a single word: reverse.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tcar-15 w-full min-h-svh grid place-items-center bg-tcar15-bg font-tcar15-sans py-10" aria-label="Moodboard marquee">
<div class="group tcar15-band w-full flex flex-col gap-4 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]">
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-run 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" decoding="async" alt="Studio still life" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" decoding="async" alt="Architectural detail" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" decoding="async" alt="Textile close-up" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" decoding="async" alt="Product on plinth" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-back 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" decoding="async" alt="Gradient backdrop" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" decoding="async" alt="Ceramic vessels" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" decoding="async" alt="Folded paper" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" decoding="async" alt="Woven basket" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
</div>
</section><section class="tcar-15 w-full min-h-svh grid place-items-center bg-tcar15-bg font-tcar15-sans py-10" aria-label="Moodboard marquee">
<div class="group tcar15-band w-full flex flex-col gap-4 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]">
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-run 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" decoding="async" alt="Studio still life" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" decoding="async" alt="Architectural detail" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" decoding="async" alt="Textile close-up" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" decoding="async" alt="Product on plinth" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-back 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" decoding="async" alt="Gradient backdrop" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" decoding="async" alt="Ceramic vessels" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" decoding="async" alt="Folded paper" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" decoding="async" alt="Woven basket" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
</div>
</section>@import "tailwindcss";
@theme {
--color-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}@import "tailwindcss";
@theme {
--color-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, 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-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}@import "tailwindcss";
@theme {
--color-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, 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&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&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Two
@themeentries pointing at one@keyframesis the tidiest thing in this port. The--animate-*namespace makes "the same motion, backwards" a named token rather than an extra declaration bolted onto a class. - The tracks are
w-max, not a percentage. A marquee's width is the sum of its content, and any attempt to express that as a utility scale is a mistake. - UI change from the CSS original: the reduced-motion fallback now centres and wraps into a genuine mosaic rather than leaving a
w-maxrow overflowing its masked band. The original's static state was clipped on the right for anyone with motion reduced.
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 Dual Opposite-Direction Marquee Slider
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-dual-opposite-direction-marquee-slider/
Two image tracks gliding in opposite directions — the top row drifts left while the bottom drifts right. One keyframe, two @theme animation tokens, and the second one differs from the first by a single word: reverse.
## HTML
```html
<section class="tcar-15 w-full min-h-svh grid place-items-center bg-tcar15-bg font-tcar15-sans py-10" aria-label="Moodboard marquee">
<div class="group tcar15-band w-full flex flex-col gap-4 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]">
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-run 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" decoding="async" alt="Studio still life" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" decoding="async" alt="Architectural detail" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" decoding="async" alt="Textile close-up" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" decoding="async" alt="Product on plinth" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-back 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" decoding="async" alt="Gradient backdrop" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" decoding="async" alt="Ceramic vessels" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" decoding="async" alt="Folded paper" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" decoding="async" alt="Woven basket" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, 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 Dual Opposite-Direction Marquee Slider
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-dual-opposite-direction-marquee-slider/
Two image tracks gliding in opposite directions — the top row drifts left while the bottom drifts right. One keyframe, two @theme animation tokens, and the second one differs from the first by a single word: reverse.
## HTML
```html
<section class="tcar-15 w-full min-h-svh grid place-items-center bg-tcar15-bg font-tcar15-sans py-10" aria-label="Moodboard marquee">
<div class="group tcar15-band w-full flex flex-col gap-4 overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_8%,#000_92%,transparent)]">
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-run 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" decoding="async" alt="Studio still life" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" decoding="async" alt="Architectural detail" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" decoding="async" alt="Textile close-up" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" decoding="async" alt="Product on plinth" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-1/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-2/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-3/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-4/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
<ul class="list-none flex gap-4 w-max m-0 p-0 animate-tcar15-back 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">
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" decoding="async" alt="Gradient backdrop" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" decoding="async" alt="Ceramic vessels" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" decoding="async" alt="Folded paper" class="size-full object-cover block"></li>
<li class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" decoding="async" alt="Woven basket" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-5/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-6/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-7/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
<li aria-hidden="true" class="flex-none w-[210px] aspect-[15/11] rounded-xl overflow-hidden bg-tcar15-tile"><img src="https://picsum.photos/seed/du-8/300/220" width="300" height="220" loading="lazy" decoding="async" alt="" class="size-full object-cover block"></li>
</ul>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tcar15-bg: #14121a;
--color-tcar15-bg: oklch(0.19 0.015 300);
--color-tcar15-tile: #221f2b;
--color-tcar15-tile: oklch(0.25 0.018 300);
--color-tcar15-acc: #f43f5e;
--color-tcar15-acc: oklch(0.65 0.21 15);
--font-tcar15-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tcar15-run: tcar15-run 30s linear infinite;
--animate-tcar15-back: tcar15-run 30s linear infinite reverse;
}
@keyframes tcar15-run {
from {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
.tcar-15 {
width: 100%;
min-height: 100svh;
}
.tcar-15 ::selection {
background: var(--color-tcar15-acc);
color: #fff;
}
/* Safari < 15.4 mask prefix. */
.tcar15-band {
-webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
```How this works
Direction is a token, not a utility. Tailwind has no animate-reverse, and should not: reversal is part of the animation's identity. A second @theme entry pointing at the same keyframe with reverse appended names the behaviour properly and mints its own utility.
Both tracks need the same two-copy contract. Each holds its images twice and the keyframe ends at exactly -50%; the duplicates carry aria-hidden="true".
One group pauses both. The band is the group, so hovering anywhere stops the whole composition rather than half of it.
Make it yours
- Independent speeds: give each token its own duration.
- Swap directions: exchange the two utilities on the tracks.
- Third row: a third token, a third track.
- Edge feather: the mask stops on the band.
Gotchas — read before shipping
- Two identical halves and a
-50%endpoint, per track. This is the one rule the pattern cannot bend. aria-hidden="true"on every duplicated tile, or the moodboard is announced twice.- Pausing must cover both tracks. A band where one row freezes and the other keeps moving reads as a bug.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
CSS animation and animation-direction are universal; mask-image needs Safari 15.4+ (shim included). The floor quoted is Tailwind v4's generated sheet.