Marquee Ribbon CTA
A dark call-to-action band framed by two infinite scrolling tag ribbons with a continuously flowing animated-gradient button and staggered centre content.
React + Tailwindnpm: motionmarquee ctascrolling ribbon banneranimated gradient buttonframer motion ctainfinite marquee tailwind
npx shadcn@latest add https://webinnoventix.com/r/acta-marquee-ribbon-cta.jsonacta-marquee-ribbon-cta.tsx
"use client";
import { motion, useReducedMotion, type Variants } from "motion/react";
const topTags = [
"Fast setup",
"No lock in",
"Free forever tier",
"Round the clock support",
"Open API",
"GDPR ready",
"99.9% uptime",
"One click deploy",
];
const bottomTags = [
"Live analytics",
"Automations",
"Integrations",
"Team roles",
"Audit logs",
"Custom domains",
"Webhooks",
"Priority queue",
];
export default function ActaMarqueeRibbonCta() {
const reduce = useReducedMotion();
const container: Variants = {
hidden: {},
show: { transition: { staggerChildren: 0.09, delayChildren: 0.1 } },
};
const rise: Variants = {
hidden: { opacity: 0, y: reduce ? 0 : 22 },
show: { opacity: 1, y: 0, transition: { duration: 0.6, ease: "easeOut" } },
};
return (
<section className="relative isolate overflow-hidden bg-gradient-to-b from-zinc-900 via-zinc-900 to-black px-6 py-20 md:py-28">
<style>{`
@keyframes acta-marq-l { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes acta-marq-r { from { transform: translateX(-50%); } to { transform: translateX(0); } }
@keyframes acta-btn-flow { to { background-position: 200% center; } }
.acta-track { display: flex; width: max-content; }
.acta-l { animation: acta-marq-l 30s linear infinite; }
.acta-r { animation: acta-marq-r 36s linear infinite; }
.acta-flow { background-size: 200% auto; animation: acta-btn-flow 4s linear infinite; }
.acta-marq:hover .acta-track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
.acta-track, .acta-flow { animation: none; }
}
`}</style>
<div aria-hidden className="pointer-events-none absolute inset-0 -z-10">
<div className="absolute left-1/2 top-1/2 h-96 w-[46rem] max-w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-r from-emerald-500/20 via-cyan-500/20 to-indigo-500/20 blur-3xl" />
</div>
<div
className="acta-marq relative [mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]"
aria-label="Product highlights"
>
<div className="acta-track acta-l gap-3">
{[...topTags, ...topTags].map((t, i) => (
<span
key={`top-${i}`}
aria-hidden={i >= topTags.length ? "true" : undefined}
className="flex shrink-0 items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-medium text-zinc-300 backdrop-blur"
>
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5 fill-emerald-400" aria-hidden>
<path d="M12 2l2.5 6.5L21 11l-6.5 2.5L12 20l-2.5-6.5L3 11l6.5-2.5L12 2z" />
</svg>
{t}
</span>
))}
</div>
</div>
<motion.div
variants={container}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.4 }}
className="relative mx-auto my-12 max-w-2xl text-center"
>
<motion.h2 variants={rise} className="text-balance text-4xl font-semibold tracking-tight text-white sm:text-5xl">
Everything you need, in one tidy place
</motion.h2>
<motion.p variants={rise} className="mx-auto mt-5 max-w-xl text-lg text-zinc-400">
Stop wiring together five different tools. Plan, build and ship from a single workspace your whole team will actually enjoy.
</motion.p>
<motion.div variants={rise} className="mt-9 flex flex-col items-center justify-center gap-3 sm:flex-row">
<motion.a
whileHover={reduce ? undefined : { y: -2 }}
whileTap={{ scale: 0.98 }}
href="#"
className="acta-flow group relative inline-flex w-full items-center justify-center gap-2 overflow-hidden rounded-full bg-[linear-gradient(110deg,#059669,#0891b2,#4f46e5,#0891b2,#059669)] px-8 py-4 text-sm font-semibold text-white shadow-lg shadow-cyan-500/25 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-900 sm:w-auto"
>
<span className="relative z-10">Start building free</span>
<svg
viewBox="0 0 24 24"
className="relative z-10 h-4 w-4"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden
>
<path d="M5 12h14M13 6l6 6-6 6" />
</svg>
<span
aria-hidden
className="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/40 to-transparent transition-transform duration-700 ease-out group-hover:translate-x-full"
/>
</motion.a>
<a
href="#"
className="inline-flex w-full items-center justify-center gap-2 rounded-full border border-white/20 bg-white/5 px-8 py-4 text-sm font-semibold text-white backdrop-blur transition hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 sm:w-auto"
>
See live demo
</a>
</motion.div>
<motion.p variants={rise} className="mt-5 text-sm text-zinc-500">
Join 12,000+ teams. Set up in under two minutes.
</motion.p>
</motion.div>
<div
className="acta-marq relative [mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]"
aria-label="More capabilities"
>
<div className="acta-track acta-r gap-3">
{[...bottomTags, ...bottomTags].map((t, i) => (
<span
key={`bottom-${i}`}
aria-hidden={i >= bottomTags.length ? "true" : undefined}
className="flex shrink-0 items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-medium text-zinc-300 backdrop-blur"
>
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5 fill-cyan-400" aria-hidden>
<path d="M12 2l2.5 6.5L21 11l-6.5 2.5L12 20l-2.5-6.5L3 11l6.5-2.5L12 2z" />
</svg>
{t}
</span>
))}
</div>
</div>
</section>
);
}Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteMore blocks
Gradient CTA
OriginalA bold gradient call-to-action banner with two buttons.
Full-Bleed Dark CTA
OriginalA full-bleed dark call-to-action banner with a live status badge, subtle grid backdrop and a primary plus secondary button pair to drive discovery calls.
Split CTA With Lead Form
OriginalA two-column call-to-action that pairs a benefit checklist with an inline name, email and message form for capturing qualified leads directly in the section.

