Animated Gradient Text with Announcement Pill

A light hero that uses one moving gradient in three places: the words inside an announcement pill, the hairline border around that pill and a highlighted phrase in the headline. The gradient runs from one colour to a second and back, and slides sideways in a seamless loop. Below the buttons, three small cards show the same text effect in other colour pairs and speeds. Everything is centred, and on phones the buttons and the three cards stack.

Code

// Adapted from Magic UI (https://magicui.design/docs/components/animated-gradient-text)
// Copyright (c) Magic UI. MIT License: https://we.inc/components/licenses
import type { CSSProperties, ReactNode } from "react";
import { ArrowRight } from "lucide-react";

const presets = [
  { name: "Sunrise", from: "#d97706", to: "#db2777", sample: "Warm and loud" },
  { name: "Lagoon", from: "#0891b2", to: "#4f46e5", sample: "Cool and calm" },
  { name: "Orchard", from: "#16a34a", to: "#b45309", sample: "Fresh and bright" },
];

/** Returns the moving gradient as inline style. `speed` stretches the gradient: higher is faster. */
function gradient(from: string, to: string, speed = 1): CSSProperties {
  return {
    backgroundImage: `linear-gradient(90deg, ${from}, ${to}, ${from})`,
    backgroundSize: `${speed * 300}% 100%`,
    ["--animated-gradient-text-announcement-pill-size" as string]: `${speed * 300}%`,
  };
}

/** Text filled with a gradient that slides sideways for ever. */
function GradientText({ children, from = "#b45309", to = "#7c3aed", speed = 1, className = "" }: { children: ReactNode; from?: string; to?: string; speed?: number; className?: string }) {
  return (
    <span className={`animated-gradient-text-announcement-pill-run bg-clip-text text-transparent ${className}`} style={gradient(from, to, speed)}>
      {children}
    </span>
  );
}

export default function AnimatedGradientTextAnnouncementPill() {
  return (
    <section className="relative overflow-hidden bg-white px-5 py-16 sm:px-6 sm:py-24">
      <style>{`
        @keyframes animated-gradient-text-announcement-pill-run {
          to { background-position: var(--animated-gradient-text-announcement-pill-size, 300%) 0; }
        }
        .animated-gradient-text-announcement-pill-run {
          animation: animated-gradient-text-announcement-pill-run 8s linear infinite;
        }
        @media (prefers-reduced-motion: reduce) {
          .animated-gradient-text-announcement-pill-run { animation: none; }
        }
      `}</style>
      <span aria-hidden="true" className="pointer-events-none absolute left-1/2 top-0 h-72 w-[720px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-amber-200/50 blur-3xl" />

      <div className="relative mx-auto max-w-4xl text-center">
        <a
          href="#"
          className="animated-gradient-text-announcement-pill-run group inline-flex rounded-full p-px shadow-sm shadow-amber-900/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-violet-500 focus-visible:ring-offset-2"
          style={gradient("#f59e0b", "#8b5cf6")}
        >
          <span className="inline-flex min-h-[40px] items-center gap-2.5 rounded-full bg-white px-4 text-sm font-medium">
            <span className="rounded-full bg-slate-900 px-2 py-0.5 text-xs font-semibold text-white">New</span>
            <GradientText>Shared calendars are here</GradientText>
            <ArrowRight aria-hidden="true" className="h-4 w-4 text-slate-500 transition-transform group-hover:translate-x-0.5" />
          </span>
        </a>

        <h1 className="mt-8 text-4xl font-semibold tracking-tight text-slate-900 sm:text-6xl sm:leading-[1.05]">
          Plan the week in one{" "}
          <GradientText from="#d97706" to="#7c3aed" speed={0.8}>
            calm, shared
          </GradientText>{" "}
          view.
        </h1>
        <p className="mx-auto mt-6 max-w-xl text-lg leading-8 text-slate-600">Tideline puts everyone's time off, deadlines and standing meetings on one page, so the Monday planning call takes ten minutes.</p>

        <div className="mt-9 flex flex-wrap items-center justify-center gap-3">
          <a href="#" className="inline-flex h-12 items-center rounded-full bg-slate-900 px-6 text-sm font-semibold text-white transition hover:bg-slate-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-slate-900 focus-visible:ring-offset-2">
            Start a free calendar
          </a>
          <a href="#" className="inline-flex h-12 items-center rounded-full border border-slate-300 px-6 text-sm font-semibold text-slate-900 transition hover:border-slate-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-slate-900 focus-visible:ring-offset-2">
            See how teams use it
          </a>
        </div>

        <ul className="mt-16 grid gap-4 text-left sm:grid-cols-3">
          {presets.map((p, i) => (
            <li key={p.name} className="rounded-2xl border border-slate-200 bg-white p-5">
              <p className="flex items-center gap-2 text-xs font-semibold uppercase tracking-widest text-slate-600">
                <span aria-hidden="true" className="h-3 w-8 rounded-full" style={{ backgroundImage: `linear-gradient(90deg, ${p.from}, ${p.to})` }} />
                {p.name}
              </p>
              <p className="mt-3 text-2xl font-semibold tracking-tight">
                <GradientText from={p.from} to={p.to} speed={1 + i * 0.5}>
                  {p.sample}
                </GradientText>
              </p>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}

Install with one command: npx shadcn@latest add https://we.inc/r/animated-gradient-text-announcement-pill.json

When to use it

How to customize it

Accessibility

Questions

How does the gradient text animation work?

The text has a linear gradient as its background, clipped to the letters with `bg-clip-text` and made visible with `text-transparent`. The background is three times wider than the text and a keyframe slides its position by exactly that width, so the loop has no visible jump.

Why does the gradient go from, to and from again?

Ending on the starting colour makes the two ends of the gradient match. When the animation restarts, the pattern lines up with where it began and the movement looks continuous.

How is the animated border on the pill made?

The link itself carries the moving gradient as its background and has one pixel of padding. A white rounded span inside covers everything except that pixel, which leaves a gradient outline.

Can I use more than two colours?

Yes. Edit the `linear-gradient` string in the `gradient` function to list more stops, and keep the first colour as the last stop so the loop stays seamless.

Does it work on a dark background?

Yes. Swap the section to a dark background, change the pill's inner span from `bg-white` to the same dark colour and pick lighter gradient colours such as `#fbbf24` and `#c084fc`.

Adapted from Animated Gradient Text in Magic UI, used under its open-source licence. Licences and credits

Related: Aurora Gradient Headline Text, Shimmering Chrome Gradient Headline, Centered Hero with Two Buttons and Logo Row.

More text effects or all free UI components. Start for free to have a full site built around it.

More in Text Effects

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap