← Particles

Sparkles

Little four-pointed stars keep twinkling in and out around a word, badge or button, for anything that deserves a bit of magic.

Something special

How to use it

  1. Paste the snippet just before </head>.
  2. Wrap the word or element in <span data-sparkles>.

Options

Add any of these attributes to the same element.

data-colorsComma-separated colours. Default gold and purple.
data-rateTime between new sparkles. Default 260 ms.
data-sizeSparkle size in em. Default 0.5.
1 · Snippet
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/bundles/anime.umd.min.js"></script>
<script>
  (function () {
    // Sparkles: little four-pointed stars keep twinkling in and out around a word
    // or element, for anything that deserves a bit of magic.
    // Usage: <span data-sparkles>New</span>
    // Optional: data-colors (comma-separated, default gold and purple),
    // data-rate (ms between new sparkles, default 260), data-size (em, default 0.5).
    var DEFAULTS = { colors: ['#facc15', '#a855f7', '#fde68a'], rate: 260, size: 0.5 };
    var STAR = 'M12 0C12.6 6.6 17.4 11.4 24 12C17.4 12.6 12.6 17.4 12 24C11.4 17.4 6.6 12.6 0 12C6.6 11.4 11.4 6.6 12 0Z';

    var css =
      '[data-sparkles]{position:relative;display:inline-block}' +
      '.spk{position:absolute;pointer-events:none;z-index:2;overflow:visible}';
    var style = document.createElement('style');
    style.textContent = css;
    document.head.appendChild(style);

    function spawn(el) {
      var d = el.dataset;
      var colors = d.colors ? d.colors.split(',').map(function (c) { return c.trim(); }) : DEFAULTS.colors;
      var R = anime.utils.random;
      var size = (+d.size || DEFAULTS.size) * R(0.5, 1.2, 2);
      var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      svg.setAttribute('viewBox', '0 0 24 24');
      svg.setAttribute('class', 'spk');
      svg.setAttribute('aria-hidden', 'true');
      svg.style.width = svg.style.height = size + 'em';
      // Anywhere over the element, spilling a little past its edges.
      svg.style.left = 'calc(' + R(-8, 100, 1) + '% - ' + size / 2 + 'em)';
      svg.style.top = 'calc(' + R(-15, 100, 1) + '% - ' + size / 2 + 'em)';
      var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      path.setAttribute('d', STAR);
      path.setAttribute('fill', colors[Math.floor(Math.random() * colors.length)]);
      svg.appendChild(path);
      el.appendChild(svg);
      anime.utils.set(svg, { scale: 0 });
      anime.animate(svg, {
        scale: [{ to: 1, duration: 350, ease: 'out(2)' }, { to: 0, duration: 450, ease: 'in(2)' }],
        rotate: [0, R(90, 180)],
        duration: 800,
        onComplete: function () { svg.remove(); }
      });
    }

    function init() {
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
      document.querySelectorAll('[data-sparkles]').forEach(function (el) {
        if (el._spk) return;
        el._spk = true;
        var timer = null;
        new IntersectionObserver(function (entries) {
          clearInterval(timer);
          if (entries[0].isIntersecting) timer = setInterval(function () { spawn(el); }, +el.dataset.rate || DEFAULTS.rate);
        }).observe(el);
      });
    }

    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
    else init();
  })();
</script>
2 · Your HTML
<h2>Meet our <span data-sparkles>new</span> plan</h2>