DEV Community

Diana Le
Diana Le

Posted on

Create Mirrored Cursor Movement with CSS and JavaScript

This week's Codepen Challenge was "Reflections" so I created a pen where a light follows your cursor and generates and mirrors the reflection on the opposite side:

Set up the light and its reflection in the HTML

<div id="container">
  <div id="flashlight"></div>
  <div id="flashlight-reflection"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Super simple: we have a container, the flashlight and the flashlight's reflection as separate divs:

Set up the CSS and Position the Lights

#flashlight,
#flashlight-reflection {
  width: 40px;
  height: 40px;
  background-color: rgba(255, 255, 255, 0.95);
  position: absolute;
  top: 50px;
  left: 50px;
  box-shadow: 0 0 20px 12px #fff;
  border-radius: 50%;
}

#flashlight-reflection {
  left: auto;
  right: 50px;
  box-shadow: 0 0 20px 12px #EB7347;
}
Enter fullscreen mode Exit fullscreen mode

This is also pretty simple. The container contains the background color and the boundary line down the middle. The cursor's flashlight and its reflection are styled almost exactly the same except for the colors and most importantly, the left and right properties for the absolutely-positioned lights. The cursor has a left property, but for the reflection we're going to use the right property instead. This will make the JavaScript simpler later on:

Dynamically Move the Lights with JavaScript

Let's walk through the more complicated parts of the JavaScript:

// set boundary of coordinates to parent div
const bounds = container.getBoundingClientRect();

// Move the cursor light and reflection on the mousemove event
function moveFlashlight(e) {
  // get mouse coordinates relative to parent
  const x = e.clientX - bounds.left;
  const y = e.clientY - bounds.top;
  // move the light with the cursor and put the cursor in the center
  flashlight.style.left = `${x - 20}px`;
  flashlight.style.top = `${y - 20}px`;
  // move the reflection based on the cursor's position
  flashlightReflection.style.right = flashlight.style.left;
  flashlightReflection.style.top = flashlight.style.top;
}
Enter fullscreen mode Exit fullscreen mode

Find the X and Y Positions of the Cursor with event.ClientX and event.ClientY

This was actually easier than I expected. Because the lights are absolutely positioned, if we can find the X and Y coordinates of the mouse cursor, we can dynamically update the CSS position with JavaScript to follow the cursor with the mousemove event. This article explains how to console.log the position of the cursor.

Set the Boundary to be the Parent Container

But in this scenario, our lights are divs within a parent container, and if your container is not the full-width of the screen, you're going to get inconsistent X and Y values based on the browser width. So we'll need to set the boundaries for these values to be the parent to make it easier. This will always make the top left corner (0, 0).

Update the Light's CSS (the Cursor)

Now that we have the X and Y coordinates we can move the flashlight to follow the cursor by changing the left and top values. You'll notice I'm subtracting 20px from both the X and Y; this is because the light is 40px wide and 40px high and I want the cursor to be in the center.

Update the Light's Reflection

Since we're mirroring on the Y-axis, in terms of moving up and down, the reflection's location will always match the cursor's Y-coordinates, so we set these equal to each other.

For the X-axis, this is more complicated. As the cursor moves closer to the center or reflection line (to the right), the reflection should move closer (to the left). Conversely if the cursor moves farther away or to the left, the reflection should move to the right. I originally created a global variable to store the previous value of X, then check if the movement is increasing and if so, then to add or subtract the position of the reflection's X-position as needed.

// Unnecessary code
if (x > xFlashlight) {
  flashlightReflection.style.right = `${x - 1}px`;
} else {
  flashlightReflection.style.right = `${x + 1}px`;
}
Enter fullscreen mode Exit fullscreen mode

Then I realized this code was completely unnecessary because of the CSS. Remember the cursor light is using the left property and the reflection is using the right property, and they are set to the same value for their respective properties when initialized. Therefore the actual numeric values will always be the same, so we can take the reflection's right value and set it equal to the cursor's left value.

Conclusion

This was a fun and difficult challenge since I had never tried anything similar, but you can see how it's relatively simple to mimic and follow cursor movement with CSS and JavaScript.

Discussion (1)

Collapse
ihtesham_haider profile image
Ihtesham Haider

Interactive