30 CSS Text Animations01 / 30

Pure CSSMIT licensed

CSS Text Sparkle Particle Highlight Hover

The 'AI feature' shimmer, done properly: a gradient badge whose four-point sparkles pop in sequence around the label on hover (clip-path stars, no images), and a display word wearing an always-on twinkle field with a hover-accelerated glitter sweep.

Published Updated

Live Demo
Try it

The code

<div class="cat-01-group">
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
<section class="cat-01a" aria-label="AI badge with sparkle particles">
  <div class="cat-01a__stage">
    <button class="cat-01a__badge" type="button">
      <span class="cat-01a__spark" style="--i:0;top:-10px;left:12%" aria-hidden="true"></span>
      <span class="cat-01a__spark" style="--i:1;top:-14px;right:20%" aria-hidden="true"></span>
      <span class="cat-01a__spark cat-01a__spark--sm" style="--i:2;bottom:-10px;right:8%" aria-hidden="true"></span>
      <span class="cat-01a__spark cat-01a__spark--sm" style="--i:3;bottom:-12px;left:26%" aria-hidden="true"></span>
      <em class="cat-01a__glyph" aria-hidden="true">✦</em>Ask AI anything
    </button>
    <p class="cat-01a__sub" aria-hidden="true">hover / focus — clip-path stars pop in sequence</p>
  </div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-01b" aria-label="Twinkling glitter text">
  <div class="cat-01b__stage">
    <h1 class="cat-01b__word" tabindex="0">shimmer<i class="cat-01b__stars" aria-hidden="true"></i></h1>
    <p class="cat-01b__sub" aria-hidden="true">always-on twinkle · hover speeds the sweep</p>
  </div>
</section>
</div>
.cat-01-group {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.cat-01-group > section {
  flex: 1 1 480px;
  min-width: min(100%,360px);
}

.cat-01a,
.cat-01a *,
.cat-01a *::before,
.cat-01a *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-01a {
  --a: oklch(0.75 0.19 300);
  --b: oklch(0.8 0.16 200);
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: radial-gradient(110% 100% at 50% 0%,#171225,#0b0913 70%);
  font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}

.cat-01a__stage {
  text-align: center;
  display: grid;
  gap: 26px;
  justify-items: center;
}

.cat-01a__badge {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: inherit;
  font-size: 17px;
  font-weight: 600;
  color: #fff;
  padding: 14px 26px;
  border: 1px solid color-mix(in oklab,var(--a) 55%,transparent);
  border-radius: 999px;
  cursor: pointer;
  background: linear-gradient(120deg,color-mix(in oklab,var(--a) 30%,#0b0913),color-mix(in oklab,var(--b) 24%,#0b0913));
  box-shadow: 0 0 0 0 transparent;
  transition: box-shadow .35s,border-color .35s;
}

.cat-01a__glyph {
  font-style: normal;
  background: linear-gradient(120deg,var(--b),var(--a));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-size: 1.15em;
}

.cat-01a__spark {
  position: absolute;
  width: 16px;
  height: 16px;
  background: linear-gradient(140deg,#fff,var(--b));
  clip-path: polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%);
  transform: scale(0);
  pointer-events: none;
  z-index: 1;
}

.cat-01a__spark--sm {
  width: 10px;
  height: 10px;
}

.cat-01a__badge:hover,
.cat-01a__badge:focus-visible {
  border-color: var(--a);
  box-shadow: 0 0 30px -6px color-mix(in oklab,var(--a) 60%,transparent),0 0 60px -18px var(--b);
}

.cat-01a__badge:hover .cat-01a__spark,
.cat-01a__badge:focus-visible .cat-01a__spark {
  animation: cat-01a-pop .75s cubic-bezier(.2,.9,.3,1.4) calc(var(--i)*90ms) both;
}

.cat-01a__badge:focus-visible {
  outline: 2px solid var(--b);
  outline-offset: 4px;
}

.cat-01a__sub {
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .16em;
  color: rgba(200,190,235,.4);
}

@keyframes cat-01a-pop {
  0% {
    transform: scale(0) rotate(0);
  }

  60% {
    transform: scale(1.25) rotate(40deg);
  }

  100% {
    transform: scale(1) rotate(45deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-01a__badge:hover .cat-01a__spark,
    .cat-01a__badge:focus-visible .cat-01a__spark {
    animation: none;
    transform: scale(1) rotate(45deg);
  }
}

.cat-01b,
.cat-01b *,
.cat-01b *::before,
.cat-01b *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-01b {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: #0d0a14;
}

.cat-01b__stage {
  text-align: center;
}

.cat-01b__word {
  position: relative;
  display: inline-block;
  font-family: 'Playfair Display',Georgia,serif;
  font-style: italic;
  font-weight: 700;
  font-size: clamp(56px,11vw,140px);
  line-height: 1.1;
  padding: 0 .15em;
  background: linear-gradient(115deg,#c9b8e8 20%,#fff 38%,#e8d5f5 46%,#a88fd0 60%,#c9b8e8 80%) 0 0/240% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: cat-01b-sweep 5.5s ease-in-out infinite;
  cursor: default;
}

.cat-01b__word:hover,
.cat-01b__word:focus-visible {
  animation-duration: 1.6s;
}

.cat-01b__word:focus-visible {
  outline: 2px solid #c9b8e8;
  outline-offset: 8px;
}

.cat-01b__stars {
  position: absolute;
  inset: -8% -4%;
  background: radial-gradient(2.5px 2.5px at 18% 30%,#fff 45%,transparent 55%),radial-gradient(2px 2px at 66% 18%,#fff 45%,transparent 55%),radial-gradient(3px 3px at 84% 62%,#fff 45%,transparent 55%),radial-gradient(2px 2px at 38% 74%,#fff 45%,transparent 55%),radial-gradient(2.5px 2.5px at 8% 66%,#fff 45%,transparent 55%);
  animation: cat-01b-twinkle 2.4s ease-in-out infinite;
  pointer-events: none;
}

.cat-01b__sub {
  margin-top: 18px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .16em;
  color: rgba(200,185,230,.4);
}

@keyframes cat-01b-sweep {
  to {
    background-position: 240% 0;
  }
}

@keyframes cat-01b-twinkle {
  0%,
    100% {
    opacity: .25;
    transform: scale(1);
  }

  50% {
    opacity: 1;
    transform: scale(1.06);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-01b__word {
    animation: none;
  }

  .cat-01b__stars {
    animation: none;
    opacity: .5;
  }
}
/* No JavaScript — four clip-path star spans pop from scale(0) with staggered keyframes while the badge ring glows; all decoration is aria-hidden. */

/* No JavaScript — a light-band gradient sweeps the clipped glyphs on a slow loop (hover shortens the duration) while a radial-gradient star field twinkles above. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Text Animation 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: CSS Text Sparkle Particle Highlight Hover
Source: https://codefronts.com/motion/css-text-animations/css-text-sparkle-particle-highlight-hover/

The 'AI feature' shimmer, done properly: a gradient badge whose four-point sparkles pop in sequence around the label on hover (clip-path stars, no images), and a display word wearing an always-on twinkle field with a hover-accelerated glitter sweep.
## HTML
```html
<div class="cat-01-group">
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
<section class="cat-01a" aria-label="AI badge with sparkle particles">
  <div class="cat-01a__stage">
    <button class="cat-01a__badge" type="button">
      <span class="cat-01a__spark" style="--i:0;top:-10px;left:12%" aria-hidden="true"></span>
      <span class="cat-01a__spark" style="--i:1;top:-14px;right:20%" aria-hidden="true"></span>
      <span class="cat-01a__spark cat-01a__spark--sm" style="--i:2;bottom:-10px;right:8%" aria-hidden="true"></span>
      <span class="cat-01a__spark cat-01a__spark--sm" style="--i:3;bottom:-12px;left:26%" aria-hidden="true"></span>
      <em class="cat-01a__glyph" aria-hidden="true">✦</em>Ask AI anything
    </button>
    <p class="cat-01a__sub" aria-hidden="true">hover / focus — clip-path stars pop in sequence</p>
  </div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">
<section class="cat-01b" aria-label="Twinkling glitter text">
  <div class="cat-01b__stage">
    <h1 class="cat-01b__word" tabindex="0">shimmer<i class="cat-01b__stars" aria-hidden="true"></i></h1>
    <p class="cat-01b__sub" aria-hidden="true">always-on twinkle · hover speeds the sweep</p>
  </div>
</section>
</div>
```
## CSS
```css
.cat-01-group {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.cat-01-group > section {
  flex: 1 1 480px;
  min-width: min(100%,360px);
}

.cat-01a,
.cat-01a *,
.cat-01a *::before,
.cat-01a *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-01a {
  --a: oklch(0.75 0.19 300);
  --b: oklch(0.8 0.16 200);
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: radial-gradient(110% 100% at 50% 0%,#171225,#0b0913 70%);
  font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}

.cat-01a__stage {
  text-align: center;
  display: grid;
  gap: 26px;
  justify-items: center;
}

.cat-01a__badge {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: inherit;
  font-size: 17px;
  font-weight: 600;
  color: #fff;
  padding: 14px 26px;
  border: 1px solid color-mix(in oklab,var(--a) 55%,transparent);
  border-radius: 999px;
  cursor: pointer;
  background: linear-gradient(120deg,color-mix(in oklab,var(--a) 30%,#0b0913),color-mix(in oklab,var(--b) 24%,#0b0913));
  box-shadow: 0 0 0 0 transparent;
  transition: box-shadow .35s,border-color .35s;
}

.cat-01a__glyph {
  font-style: normal;
  background: linear-gradient(120deg,var(--b),var(--a));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-size: 1.15em;
}

.cat-01a__spark {
  position: absolute;
  width: 16px;
  height: 16px;
  background: linear-gradient(140deg,#fff,var(--b));
  clip-path: polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%);
  transform: scale(0);
  pointer-events: none;
  z-index: 1;
}

.cat-01a__spark--sm {
  width: 10px;
  height: 10px;
}

.cat-01a__badge:hover,
.cat-01a__badge:focus-visible {
  border-color: var(--a);
  box-shadow: 0 0 30px -6px color-mix(in oklab,var(--a) 60%,transparent),0 0 60px -18px var(--b);
}

.cat-01a__badge:hover .cat-01a__spark,
.cat-01a__badge:focus-visible .cat-01a__spark {
  animation: cat-01a-pop .75s cubic-bezier(.2,.9,.3,1.4) calc(var(--i)*90ms) both;
}

.cat-01a__badge:focus-visible {
  outline: 2px solid var(--b);
  outline-offset: 4px;
}

.cat-01a__sub {
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .16em;
  color: rgba(200,190,235,.4);
}

@keyframes cat-01a-pop {
  0% {
    transform: scale(0) rotate(0);
  }

  60% {
    transform: scale(1.25) rotate(40deg);
  }

  100% {
    transform: scale(1) rotate(45deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-01a__badge:hover .cat-01a__spark,
    .cat-01a__badge:focus-visible .cat-01a__spark {
    animation: none;
    transform: scale(1) rotate(45deg);
  }
}

.cat-01b,
.cat-01b *,
.cat-01b *::before,
.cat-01b *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-01b {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: #0d0a14;
}

.cat-01b__stage {
  text-align: center;
}

.cat-01b__word {
  position: relative;
  display: inline-block;
  font-family: 'Playfair Display',Georgia,serif;
  font-style: italic;
  font-weight: 700;
  font-size: clamp(56px,11vw,140px);
  line-height: 1.1;
  padding: 0 .15em;
  background: linear-gradient(115deg,#c9b8e8 20%,#fff 38%,#e8d5f5 46%,#a88fd0 60%,#c9b8e8 80%) 0 0/240% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: cat-01b-sweep 5.5s ease-in-out infinite;
  cursor: default;
}

.cat-01b__word:hover,
.cat-01b__word:focus-visible {
  animation-duration: 1.6s;
}

.cat-01b__word:focus-visible {
  outline: 2px solid #c9b8e8;
  outline-offset: 8px;
}

.cat-01b__stars {
  position: absolute;
  inset: -8% -4%;
  background: radial-gradient(2.5px 2.5px at 18% 30%,#fff 45%,transparent 55%),radial-gradient(2px 2px at 66% 18%,#fff 45%,transparent 55%),radial-gradient(3px 3px at 84% 62%,#fff 45%,transparent 55%),radial-gradient(2px 2px at 38% 74%,#fff 45%,transparent 55%),radial-gradient(2.5px 2.5px at 8% 66%,#fff 45%,transparent 55%);
  animation: cat-01b-twinkle 2.4s ease-in-out infinite;
  pointer-events: none;
}

.cat-01b__sub {
  margin-top: 18px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .16em;
  color: rgba(200,185,230,.4);
}

@keyframes cat-01b-sweep {
  to {
    background-position: 240% 0;
  }
}

@keyframes cat-01b-twinkle {
  0%,
    100% {
    opacity: .25;
    transform: scale(1);
  }

  50% {
    opacity: 1;
    transform: scale(1.06);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-01b__word {
    animation: none;
  }

  .cat-01b__stars {
    animation: none;
    opacity: .5;
  }
}
```

## JavaScript
```js
/* No JavaScript — four clip-path star spans pop from scale(0) with staggered keyframes while the badge ring glows; all decoration is aria-hidden. */

/* No JavaScript — a light-band gradient sweeps the clipped glyphs on a slow loop (hover shortens the duration) while a radial-gradient star field twinkles above. */
```

How this works

Each sparkle is an empty span cut into a four-point star with one clip-path:polygon(); at rest it sits at scale(0). Hover pops them with a keyframe that scales up, spins 45° and settles, staggered by --i:

.spark{clip-path:polygon(50% 0,62% 38%,100% 50%,62% 62%,
  50% 100%,38% 62%,0 50%,38% 38%);transform:scale(0)}
.badge:hover .spark{animation:pop .7s calc(var(--i)*90ms) both}

The twinkle-field variant paints stars into the text itself: the word is gradient-clipped, and an ::after overlay carries a radial-gradient star field masked to the glyphs, blinking via opacity keyframes; hovering sweeps a diagonal shine band (translated background-position) through the letters.

Make it yours

  • Sparkle count: 3–5 reads premium, 8+ reads confetti.
  • Trade the pop for a orbit: animate translate around the badge with offset-path.
  • Sync sparkle color to the badge gradient via one --accent token.
  • Make the shimmer always-on (slow) and hover only accelerates it — great for 'New' badges.

Gotchas — read before shipping

  • Sparkles are decorative — aria-hidden, pointer-events:none, and never part of the accessible name.
  • Keep sparkle layers inside the badge's stacking context (isolation:isolate) so they never float over neighboring UI.
  • Respect reduced motion: show the badge lit but static.

Browser support

ChromeSafariFirefoxEdge
111+16.2+113+111+

Floor set by oklch(), color-mix() as this demo is written. The core technique itself goes back further — Chrome 55+.

clip-path polygons and masks are evergreen-universal; without mask support the twinkle overlay simply doesn't paint and the text stays clean.

Techniques used in this demo

Search CodeFronts

Loading…