Google AI Mode Button — Rainbow Border Glow That Sweeps & Follows the Cursor

AI Mode Glow Button (Google Search Style) · Buttons · Plain HTML, CSS & JS · Live preview

CategoryButtons

What's included

Features

Faithful recreation of the rainbow border glow on the AI Mode button Google uses in the google.com search box
Intro animation sweeps the glow 180deg from the left edge over the top to the right, then fades
Glow slides round the border to face the cursor while hovering, along the shortest path
Optional data-proximity wakes the glow before the cursor touches the button
Colour disc (conic-gradient) spun by --c so hues drift as the glow moves
Two intersected conic-gradient masks form a soft-ended wedge, rotated by --a
Mask stretched with scale() so the arc hugs a long pill evenly, with cursor maths that matches
Soft 4px bloom plus crisp 1px edge layer, both clipped to the button rim
JS writes only --a, --c and --o; a self-stopping requestAnimationFrame loop costs nothing when idle
Light and dark search-bar variants and a large CTA; tap-to-sweep on touch; reduced-motion aware
Export as HTML file, React JSX, or React + Tailwind CSS

About this UI Snippet

Google AI Mode Button — How the Rainbow Glow Sweeps on Load and Tracks the Cursor

Screenshot of the AI Mode Glow Button (Google Search Style) snippet rendered live

Google uses this button on its own homepage. In the google.com search box, next to the voice search and Google Lens icons, sits an "AI Mode" pill (its tooltip reads "Ask AI Mode in Google Search") that takes your query into Google's AI Mode — the conversational, AI-powered way to search. Because it's on one of the most visited pages on the web, it's become a familiar pattern for how an "AI" entry point looks and behaves.

It also has a small detail you notice without quite knowing why: when the page loads, a soft multicolour glow appears on the left edge, travels over the top to the right edge and fades out. Hover the button and the glow comes back, sliding round the border to whichever side your cursor is on. This snippet rebuilds that effect with the same layering approach Google's button uses (inspected from google.com's live CSS) — light and dark search bars, plus a larger call-to-action that wakes up before the cursor even touches it. It's an independent recreation for learning and for your own projects, not Google's code, and isn't affiliated with Google.

A colour disc behind a moving mask

The colours come from one element: a circle filled with a conic-gradient of blue, violet, pink, red, orange, yellow, green and teal. On its own that would just be a rainbow wheel. It sits inside a mask made of two conic-gradients combined with mask-composite: intersect — each lets through a different slice of the circle, and only the overlap stays visible, leaving a single wedge that is soft at both ends. Both gradients start at from var(--a), so changing --a turns the wedge, and with it the lit part of the border. A second property, --c, rotates the colour disc underneath, so the hues drift as the glow moves.

Stretching the wedge into an arc along a pill

A wedge cut from the centre of a wide pill would light the long top and bottom edges unevenly. The fix is scale: var(--sx) var(--sy) (4 × 1.5 here) on the masked element: the wedge is stretched horizontally so it sweeps along the flat edges and wraps the rounded ends smoothly. The layer around it has overflow: hidden and inset: -1px, so everything outside the button plus one pixel is clipped away.

Two layers: a bloom and an edge

The glow is drawn twice. One layer is blurred by 4px and gives the soft coloured halo that spills just past the button. The other is blurred by only 1px and uses a narrower wedge, giving a crisper line right on the border. The opaque button face sits on top of both, so you never see the rainbow inside the button — only the rim and the bloom around it. The whole group is held at 60% opacity so the effect stays subtle.

The intro sweep, half-way round

About 0.3 seconds after load each button runs a 1.3-second intro. The mask angle travels 180 degrees with an ease-out curve — fast at first, settling at the end — so the glow starts at 9 o'clock, goes over the top and ends at 3 o'clock. It fades in over the first 10%, holds, and fades out over the last 45%, while the colour disc turns about 45 degrees so the hues shift as it goes. Buttons are staggered by 180ms, and the Replay link runs it again.

Following the cursor

A single pointermove listener checks each button. When the cursor is over it (or within its data-proximity distance, like the large CTA's 70px), the script takes the angle from the button's centre to the cursor. Because the mask is stretched, the cursor offset is divided by the same scale first, so the glow really lands on the nearest side. atan2 counts from 3 o'clock and conic gradients from 12 o'clock, so 90 degrees is added, then the wedge's own position inside the mask (257 degrees) is subtracted. The glow eases toward that angle along the shortest path, the colours follow more slowly, and when the cursor leaves the glow fades out where it is.

Cheap to run

JavaScript only writes three custom properties per button. The requestAnimationFrame loop stops once everything has settled, so an idle page does no work. With prefers-reduced-motion the intro is skipped and the glow snaps to the cursor instead of easing. On touch screens, where there is no hover, a tap plays the sweep.

Build with AI

Build, Understand, Optimize, and Extend It With AI

The best way to understand this effect is to take it apart with an AI coding assistant like Claude. Paste the HTML, CSS and JS and ask what the two intersected conic-gradient masks produce on their own, why the masked element is scaled 4 × 1.5, or where the 257-degree offset comes from. Then experiment: ask for a full-lap intro, a "thinking" state where the glow circles continuously while an AI answer streams in, a single-colour brand version, or a React hook that wraps the whole thing. The JavaScript only feeds three numbers into CSS, so each change stays small and easy to follow.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a Google Search "AI Mode"-style pill button in plain HTML, CSS and JavaScript with no libraries.

Requirements:
- A 36px-tall pill button (search-sparkle icon + "AI Mode") inside a search bar, plus a dark search bar variant and a larger standalone button.
- Behind an opaque button face, add a glow group at 60% opacity containing two layers (inset: -1px, overflow: hidden): one blurred 4px, one blurred 1px.
- In each layer put a masked element scaled 4 × 1.5, whose mask is two conic-gradients starting at var(--a) combined with mask-composite: intersect so a single soft-ended wedge stays visible (the 1px layer uses a narrower wedge). Include -webkit-mask-image and -webkit-mask-composite: source-in.
- Inside the mask, a full-width circle filled with a multicolour conic-gradient (blue, violet, pink, red, orange, yellow, green, teal) and rotated by var(--c).
- JavaScript writes only --a (mask angle), --c (colour rotation) and --o (opacity).
- On load, sweep --a through 180 degrees with an ease-out curve so the glow travels from the left edge over the top to the right edge, fading in quickly and out over the last ~45%; stagger multiple buttons.
- While the cursor is over a button (or within an optional data-proximity distance), point the glow at the cursor: divide the cursor offset from the centre by the mask scale, take atan2, add 90 degrees and subtract the wedge's offset inside the mask. Ease --a along the shortest path and let --c follow more slowly; fade out when the cursor leaves.
- Use a requestAnimationFrame loop that stops when everything has settled, play the sweep on tap for touch devices, and skip the intro / snap instead of easing under prefers-reduced-motion.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="aim-page">
  <p class="aim-hint">On load the glow sweeps half-way round each button, from the left edge over the top to the right. Then hover a button and move along it — the glow slides round the border to the side nearest your cursor.</p>

  <!-- Light search bar -->
  <div class="aim-search">
    <span class="aim-plus" aria-hidden="true">+</span>
    <input class="aim-input" type="text" placeholder="Ask anything" aria-label="Search">
    <span class="aim-icon" aria-hidden="true">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/></svg>
    </span>
    <span class="aim-icon" aria-hidden="true">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 8V6a2 2 0 0 1 2-2h2M16 4h2a2 2 0 0 1 2 2v2M20 16v2a2 2 0 0 1-2 2h-2M8 20H6a2 2 0 0 1-2-2v-2"/><circle cx="12" cy="12" r="3"/></svg>
    </span>
    <button class="aim-btn" type="button">
      <span class="aim-glow" aria-hidden="true">
        <span class="aim-fx">
          <span class="aim-layer aim-soft"><span class="aim-mask"><span class="aim-disc"></span></span></span>
          <span class="aim-layer aim-sharp"><span class="aim-mask"><span class="aim-disc"></span></span></span>
        </span>
      </span>
      <span class="aim-face"></span>
      <span class="aim-label">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><circle cx="10" cy="10" r="6"/><path d="M14.5 14.5 20 20"/><path d="M19 2.5v5M16.5 5h5" stroke-width="1.8"/></svg>
        AI Mode
      </span>
    </button>
  </div>

  <!-- Dark search bar -->
  <div class="aim-search aim-dark">
    <span class="aim-plus" aria-hidden="true">+</span>
    <input class="aim-input" type="text" placeholder="Ask anything" aria-label="Search (dark)">
    <button class="aim-btn" type="button">
      <span class="aim-glow" aria-hidden="true">
        <span class="aim-fx">
          <span class="aim-layer aim-soft"><span class="aim-mask"><span class="aim-disc"></span></span></span>
          <span class="aim-layer aim-sharp"><span class="aim-mask"><span class="aim-disc"></span></span></span>
        </span>
      </span>
      <span class="aim-face"></span>
      <span class="aim-label">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><circle cx="10" cy="10" r="6"/><path d="M14.5 14.5 20 20"/><path d="M19 2.5v5M16.5 5h5" stroke-width="1.8"/></svg>
        AI Mode
      </span>
    </button>
  </div>

  <!-- Large CTA: data-proximity wakes the glow 70px before the cursor touches it -->
  <button class="aim-btn aim-lg" type="button" data-proximity="70">
    <span class="aim-glow" aria-hidden="true">
      <span class="aim-fx">
        <span class="aim-layer aim-soft"><span class="aim-mask"><span class="aim-disc"></span></span></span>
        <span class="aim-layer aim-sharp"><span class="aim-mask"><span class="aim-disc"></span></span></span>
      </span>
    </span>
    <span class="aim-face"></span>
    <span class="aim-label">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><circle cx="10" cy="10" r="6"/><path d="M14.5 14.5 20 20"/><path d="M19 2.5v5M16.5 5h5" stroke-width="1.8"/></svg>
      Ask AI anything
    </span>
  </button>

  <button class="aim-replay" type="button" id="aimReplay">&#8635; Replay intro sweep</button>
</div>

Step by step

How to Use

  1. 1
    Watch the intro sweepReload the preview or click "Replay intro sweep". The glow appears on each button's left edge, travels over the top to the right edge and fades out, one button after another.
  2. 2
    Hover and move along a buttonPut the cursor on the AI Mode button and slide it from the left end to the right end, then above and below. The glow slides round the border to face the cursor.
  3. 3
    Try the proximity variantApproach the large "Ask AI anything" button. Its data-proximity="70" wakes the glow 70px away, getting brighter as you get closer. Add the attribute to any button, or remove it for hover-only like Google.
  4. 4
    Tune the motionIn the JS panel change INTRO_MS and INTRO_SWEEP (try 360 for a full lap), FOLLOW for how quickly the glow chases the cursor, and HUE_FOLLOW for how fast the colours drift.
  5. 5
    Change the coloursEdit the conic-gradient stops on .aim-disc in the CSS panel. Use your brand colours, or a two-colour gradient for a calmer look.
  6. 6
    Adjust the glow shapeChange --sx and --sy to reshape the lit arc for wider or taller buttons, the blur() values on .aim-layer and .aim-sharp for softness, and the .aim-glow opacity for strength.
  7. 7
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

AI
AI entry points in search bars
Exactly how Google uses it: a button inside the search box that switches a normal search into an AI or chat mode — the glow says "something smarter lives here" without shouting. Pairs well with the AI prompt composer.
Copilot and assistant toggles
Use it for the "Ask AI" button in an editor toolbar or dashboard header, next to the AI sidebar it opens.
BTN
Premium CTAs on landing pages
The large variant with data-proximity makes a hero call-to-action that lights up as visitors move toward it.
New-feature attention cue
Call playIntro() once when an AI feature launches, or after onboarding, to draw the eye to it a single time.
Learn conic gradients and CSS masks
A compact lesson in conic-gradient angles, mask-composite: intersect, stretching masks with scale, and driving CSS from custom properties.
Related: Proximity Glow Button
The Proximity Glow Button uses a similar distance idea for brightness only. This one adds direction and colour.

Got questions?

Frequently Asked Questions

On the google.com homepage, inside the main search box to the right of the voice search and Google Lens icons. Its tooltip reads "Ask AI Mode in Google Search", and clicking it sends your query to Google's AI Mode instead of the classic results page. The glow sweeps round it once when the page loads and follows the cursor when you hover it — the behaviour this snippet recreates.

It stacks a rainbow conic-gradient disc behind a mask made of two intersected conic gradients. The mask leaves one soft wedge visible, and rotating the mask's start angle moves the wedge round the button. The button's opaque face covers the middle, so only the rim and a blurred bloom show. This snippet uses the same approach.

A wedge cut from the centre of a wide, short pill would light the long top and bottom edges unevenly. Stretching the masked layer makes the wedge sweep along the flat edges and wrap round the rounded ends smoothly. The cursor angle is divided by the same scale so the glow still lands on the side nearest the cursor.

One layer is blurred by 4px for the soft coloured halo. The other is blurred by 1px with a narrower wedge for a sharper line on the edge. Together they look lit rather than outlined.

Not by default. Like Google's, it reacts while the cursor is on the button. Add data-proximity="70" (any pixel value) to a button to make it wake up that far away and brighten as the cursor approaches, as the large demo button does.

Current Chrome, Edge, Firefox and Safari. It relies on conic-gradient, mask-image with mask-composite: intersect, and the individual scale/rotate/translate properties. The -webkit-mask-image and -webkit-mask-composite: source-in lines cover older WebKit builds.

No. JavaScript only writes three custom properties per button, and the animation loop stops as soon as everything settles. The only per-move work is one getBoundingClientRect per button.

Yes. Click "JSX" to export. In your own component, attach the pointermove listener in a useEffect and write --a, --c and --o with ref.current.style.setProperty instead of React state, so moving the mouse never triggers re-renders.