If I wanted to create a box that moves along with the mouse cursor, I could achieve that using the code below.
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});
.box {
width: 50px;
height: 50px;
background-color: blue;
transform: translate(calc(var(--mouse-x) - 50%), calc(var(--mouse-y) - 50%));
}
<div class="box"></div>
However, if the element is not positioned at the top left corner, this method will no longer work as expected.
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});
.box {
width: 50px;
height: 50px;
margin-left: 150px;
background-color: blue;
transform: translate(calc(var(--mouse-x) - 50%), calc(var(--mouse-y) - 50%));
}
<div class="box"></div>
I am looking for a way to use absolute coordinates in conjunction with a CSS transform without disrupting the flow of elements. One approach could be to calculate the central position of the element dynamically through JavaScript.
document.addEventListener('mousemove', (e) => {
document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});
window.addEventListener('load', (e) => {
const box = document.querySelector('.box');
const rect = box.getBoundingClientRect();
box.setAttribute('style', `
--center-x: ${rect.left + (rect.width / 2)}px;
--center-y: ${rect.top + (rect.height / 2)}px;
`);
});
.box {
width: 50px;
height: 50px;
margin-left: 150px;
background-color: blue;
transform: translate(calc(var(--mouse-x) - var(--center-x)), calc(var(--mouse-y) - var(--center-y)));
}
<div class="box"></div>
Although this solution works, it is not perfect and can easily be disrupted by changes on the page. Additionally, performance may suffer when multiple elements are involved. Is there a more efficient method to accomplish this task using CSS or Vanilla JS?