Saturday, May 24, 2025
HomeCSSLearn how to create a customized JavaScript sparkle cursor

Learn how to create a customized JavaScript sparkle cursor


By the top of this tutorial, you’ll have created one thing like this:

HTML construction

Our HTML construction can be very minimal, that includes nothing greater than a cursor and a paragraph. Right here is all of the HTML we want:

1
<div class="title">Transfer your cursor round to see the sparkles</div>
2
<div class="cursor"></div>

Styling the cursor and sparkle path

Within the demo, you’ll discover we’ve got a customized cursor with trailing sparkles that observe the mouse motion. To realize this, we’ll conceal the default cursor after which create our personal customized cursor with a glowing path.

Listed here are the kinds wanted for the glint cursor software.

1
physique {
2
  margin: 0;
3
  peak: 100vh;
4
  background-color: #121212;
5
  cursor: none;
6
  overflow: hidden;
7
  show: flex;
8
  justify-content: middle;
9
  align-items: middle;
10
}
11

12
.title {
13
  colour: white;
14
  font-size: 1rem;
15
  text-align: middle;
16
}
17

18
.cursor {
19
  place: absolute;
20
  width: 20px;
21
  peak: 20px;
22
  border-radius: 50%;
23
  background-color: rgba(255, 255, 255, 0.5);
24
  pointer-events: none;
25
  rework: translate(-50%, -50%);
26
  z-index: 9999;
27
}
28

29
.cursor-trail {
30
  place: absolute;
31
  border-radius: 50%;
32
  pointer-events: none;
33
  rework: translate(-50%, -50%);
34
}

Add JavaScript to see the magic

Let’s first get the cursor factor from the HTML.

1
const cursor = doc.querySelector(".cursor");

Subsequent, let’s outline a set of vibrant colours for the sparkles. You may customise the colours as you want. Right here is the array containing the colours I’m working with.

1
const colours = [
2
    "#FFD700",
3
    "#FF8C00",
4
    "#FF4500",
5
    "#FB68EE",
6
    "#FF69B4",
7
    "#00CED1",
8
  ];

The following step is to trace mouse actions on the web page and replace the place of our customized cursor based mostly on the mouse’s clientX and clientY positions. 

1
doc.addEventListener("mousemove", (e) => {
2
    cursor.type.left = e.clientX + "px";
3
    cursor.type.high = e.clientY + "px";
4

5
  });

Each clientX and clientY are properties of a mouse in JavaScript. clientX offers you the horizontal place of the mouse pointer relative to the viewport, whereas clientY offers you the vertical place of the mouse pointer relative to the viewport.

In different phrases, once you transfer your mouse on a webpage, clientX and clientY will exactly let you know the place of the mouse. These values are measured from the highest left nook of the present seen window.

Easy demonstration utilizing code

Simply to actually provide you with an concept of what we’re doing, copy the next code:

1
window.addEventListener('mousemove', (e) => {
2
  console.log(`X: ${e.clientX}, Y: ${e.clientY}`);
3
});

Should you paste this code in your browser’s console tab and transfer your mouse across the display, you will notice the positions updating in real-time.

Create a Sparkle

A sparkle is just a small spherical factor that seems alongside the mouse path including a magical impact. To generate these sparkles, we’ll create a component for every sparkle, apply kinds and animations, and dynamically place them at random positions from the mouse place.

Create a operate known as createSparkle() that may deal with the era of every sparkle factor.

1
operate createSparkle(x, y) {
2
 const sparkle = doc.createElement("div");
3
 sparkle.classList.add("cursor-trail");
4

5
}

This div will act as a sparkle. To make sure every sparkle is exclusive when it comes to dimension, colour, and distance,  we’ll use  Math.random() to assign random values to a couple properties.

1
const colour = colours[Math.floor(Math.random() * colors.length)];
2
const dimension = Math.random() * 15 + 5;
3
const angle = Math.random() * Math.PI * 2;
4
const distance = Math.random() * 50 + 10;

Here’s a breakdown of every property:

  • colour: a random colour picked from the colours array
  • dimension: a random dimension between 5px and 20px to maintain the sparkles small in dimension
  • distance: That is the gap of the glint from the cursor place
  • angle: The course through which the glint will transfer

Apply the outlined properties as kinds.

1
sparkle.type.backgroundColor = colour;
2
sparkle.type.boxShadow = `0 0 10px ${colour}`;
3
sparkle.type.width = `${dimension}px`;
4
sparkle.type.peak = `${dimension}px`;

We additionally must place the glint on the present mouse location to make sure every sparkle begins on the mouse’s place earlier than transferring outward. 

1
sparkle.type.left = `${x}px`;
2
sparkle.type.high = `${y}px`;

Lastly, add the glint to the web page.

1
doc.physique.appendChild(sparkle);

Animating the Sparkle

In CSS, animations are sometimes created utilizing keyframes. Keyframes enable us to outline how a component’s properties change over time. As an illustration, to attain the impact wanted for our sparkles, we’ll animate two properties, primarily opacity (for fading out) and tranform (to make the glint transfer away from the cursor place).

We’ll apply these keyframes utilizing the JavaScript net Animations API and the animation will seem like this:

1
sparkle.animate(
2
  [
3
    {
4
      opacity: 1,
5
      transform: "translate(-50%,-50%) scale(1)",
6
    },
7
    {
8
      opacity: 0,
9
      transform: `translate(calc(-50% + ${
10
        Math.cos(angle) * distance
11
      }px), calc(-50% + ${Math.sin(angle) * distance}px)) scale(0)`,
12
    },
13
  ],
14
 
15
);

Let’s break down the animation logic

Keyframes outline completely different states of an animation. In our case, we’ve got two states:

  • Preliminary state: The sparkles begins at opacity: 1 (absolutely seen), translate (-50% ,-50%) facilities the glint precisely on the cursor place, and scale(1) means the glint is its unique dimension.
  • Ultimate state: The flicker fades out with opacity:0. The translate(calc (...)) strikes the glint from the middle by a calculated distance and scale (0) shrinks it utterly.

Let’s add a period and an easing operate for a easy animation.

1
operate createSparkle(x, y) {
2
    const sparkle = doc.createElement("div");
3
    sparkle.classList.add("cursor-trail");
4

5
    const colour = colours[Math.floor(Math.random() * colors.length)];
6
    const dimension = Math.random() * 15 + 5;
7
    const angle = Math.random() * Math.PI * 2;
8
    const distance = Math.random() * 50 + 10;
9

10
    sparkle.type.backgroundColor = colour;
11
    sparkle.type.boxShadow = `0 0 10px ${colour}`;
12
    sparkle.type.width = `${dimension}px`;
13
    sparkle.type.peak = `${dimension}px`;
14
    sparkle.type.left = `${x}px`;
15
    sparkle.type.high = `${y}px`;
16

17
    doc.physique.appendChild(sparkle);
18

19

20
    sparkle.animate(
21
      [
22
        {
23
          opacity: 1,
24
          transform: "translate(-50%,-50%) scale(1)",
25
        },
26
        {
27
          opacity: 0,
28
          transform: `translate(calc(-50% + ${
29
            Math.cos(angle) * distance
30
          }px), calc(-50% + ${Math.sin(angle) * distance}px)) scale(0)`,
31
        },
32
      ],
33
      {
34
        period: 1000,
35
        easing: "cubic-bezier(0.4, 0, 0.2, 1)",
36
        fill: "forwards",
37
      }
38
    );
39
    setTimeout(() => {
40
      sparkle.take away();
41
    }, 1000);
42
  }

Here’s what every property does:

  • period:100: runs the animation for one second
  • easing: "cubic-bezier(0.4, 0, 0.2, 1)": Ensures easy motion
  • fill: "forwards":  ensures the sparkles fades out after the animation ends.

Take away the glint factor from the DOM after the animation is completed.

1
setTimeout(() => {
2
  sparkle.take away();
3
}, 1000);

The ultimate code for the createSparkle() operate will seem like this:

1
operate createSparkle(x, y) {
2
    const sparkle = doc.createElement("div");
3
    sparkle.classList.add("cursor-trail");
4

5
    const colour = colours[Math.floor(Math.random() * colors.length)];
6
    const dimension = Math.random() * 15 + 5;
7
    const angle = Math.random() * Math.PI * 2;
8
    const distance = Math.random() * 50 + 10;
9

10
    sparkle.type.backgroundColor = colour;
11
    sparkle.type.boxShadow = `0 0 10px ${colour}`;
12
    sparkle.type.width = `${dimension}px`;
13
    sparkle.type.peak = `${dimension}px`;
14
    sparkle.type.left = `${x}px`;
15
    sparkle.type.high = `${y}px`;
16

17
    doc.physique.appendChild(sparkle);
18

19
    sparkle.animate(
20
      [
21
        {
22
          opacity: 1,
23
          transform: "translate(-50%,-50%) scale(1)",
24
        },
25
        {
26
          opacity: 0,
27
          transform: `translate(calc(-50% + ${
28
            Math.cos(angle) * distance
29
          }px), calc(-50% + ${Math.sin(angle) * distance}px)) scale(0)`,
30
        },
31
      ],
32
      {
33
        period: 1000,
34
        easing: "cubic-bezier(0.4, 0, 0.2, 1)",
35
        fill: "forwards",
36
      }
37
    );
38
    setTimeout(() => {
39
      sparkle.take away();
40
    }, 1000);
41
  }

Lastly, let’s allow contact occasions for cell units. This may guarantee the glint impact on cell units work by monitoring the finger motion.

1
doc.addEventListener(
2
    "touchmove",
3
    (e) => {
4
      e.preventDefault();
5
      const contact = e.touches[0];
6
      cursor.type.left = contact.clientX + "px";
7
      cursor.type.high = contact.clientY + "px";
8
      createSparkle(contact.clientX, contact.clientY);
9
    },
10
    { passive: false }
11
  );

Finish consequence

Right here is the ultimate demo!

Conclusion

That’s it for our sparkle cursor. The very best half about customized cursors is that the chances are infinite. You may experiment with completely different shapes, animations, photos, and even content material to create distinctive and memorable customized cursors. Get pleasure from!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments