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>
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;
}
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;
}
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`;
}
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.
Top comments (1)
Interactive