Aurora Background
BackgroundsAmbient gradient field: three soft colour fields drifting at three coprime speeds, a slow hue rotation so the colours themselves move, and a film-grain layer stepped at 12 fps.
A gradient fill drifting slowly through the text with no seam at the loop point. Only the background position moves. Pure CSS; works on any inline or block text.
Gradient that never seams.
Live, from the library itself: scroll, hover, navigate away and back. The demo is never gated.
Adjust · props are custom properties, set inline, so you edit the running instance
JavaScript of its own
0 B
CSS 4.5 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.
Browser support
Chrome 120 · Firefox 49 · Safari 14; needs bg-clip-text.
One command adds the integration, the base tokens and every component. Then import what you use.
npx astro add moonarcpnpm astro add moonarcbunx astro add moonarc---
import GradientText from '@moonarc/core/GradientText';
---
<h1><GradientText>Motion for Astro.</GradientText></h1>
<GradientText colors={['#f59e0b', '#ec4899']} angle={45} duration={4}>two colours</GradientText>Owns the file, no dependency. The registry item also installs the base tokens.
npx shadcn@latest add https://moonarc.dev/r/gradient-text.jsonThe CLI needs a components.json and the @/* alias, which Setup has. The file lands in src/components/moonarc/.
The whole component. Self-contained styles in a cascade layer so your classes always win; it imports nothing.
---
/**
* GradientText — a gradient fill that drifts through the text, zero JS.
*
* The gradient is three times wider than the text and only its position
* moves: no layout, though background-position is not composited, so each
* frame repaints the text's own box. The last stop repeats the first so the
* loop has no seam.
*/
import type { HTMLAttributes, HTMLTag } from 'astro/types';
interface Props extends HTMLAttributes<'span'> {
/** Element to render. */
as?: HTMLTag;
/** Colours, 2–5, any CSS colour. */
colors?: string[];
/** Seconds per full drift. */
duration?: number;
/** Gradient angle in degrees. */
angle?: number;
}
const { as: Tag = 'span', colors = ['oklch(70% 0.19 300)', 'oklch(78% 0.15 200)', 'oklch(75% 0.17 350)'], duration = 6, angle = 90, class: className, style, ...rest } = Astro.props;
const stops = [...colors.slice(0, 5), colors[0]].join(', ');
// the caller's style joins the component's instead of replacing it: a style prop used to drop the stops, and the text,
// transparent over no gradient, disappeared
const vars = [`--ma-gt-stops:${stops}`, `--ma-gt-duration:${duration}s`, `--ma-gt-angle:${angle}deg`, typeof style === 'string' ? style : ''].filter(Boolean).join(';');
---
<Tag class:list={['ma-gradient-text', className]} style={vars} {...rest}><slot /></Tag>
<style is:global>
@layer components {
:where(.ma-gradient-text) {
background-image: linear-gradient(var(--ma-gt-angle, 90deg), var(--ma-gt-stops));
background-size: 300% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: ma-gradient-text var(--ma-gt-duration, 6s) linear infinite;
}
@media (prefers-reduced-motion: reduce) {
:where(.ma-gradient-text) {
animation: none;
}
}
/* Print drops backgrounds by default, and with them the only paint the transparent text had: it prints in the
colour around it instead. */
@media print {
:where(.ma-gradient-text) {
color: inherit;
background: none;
animation: none;
}
}
}
@keyframes ma-gradient-text {
to {
background-position: -300% 0;
}
}
</style>| Prop | Type | Default | Description |
|---|---|---|---|
as | HTMLTag | 'span' | Element to render. |
colors | string[] | violet, cyan, rose (oklch) | 2–5 colours. The first is repeated at the end so the loop has no visible seam. |
duration | number | 6 | Seconds per full drift. Under 3 flickers. |
angle | number | 90 | Gradient angle in degrees. |
The gradient stays put.
ClientRouterCSS-only; nothing to rebind.
Replaces: GradientText (React Bits) · AnimatedGradientText (Magic UI). See the migration table.
Ambient gradient field: three soft colour fields drifting at three coprime speeds, a slow hue rotation so the colours themselves move, and a film-grain layer stepped at 12 fps.
Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown