I can make a box that follows the mouse with the following.
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>
but as soon as the element is not positioned at the top left, it breaks.
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>
How can I use absolute coordinates with a transform? I don't want to use left/top/position: fixed/absolute because I need to preserve the position of the element in the flow.
I could use JavaScript to grab the central position and then use that infomation to get the correct center.
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>
This works, but it's not ideal and easily broken if anything else in the page changes. It also slows down with more elements, and I'd like it to be as fast as possible. It there a better way to do this? I'm fine using CSS/Vanilla JS.
You don't have to use translate() please I would recommend you to use the left and top properties in CSS. They can help you position an element based on coordinates.
window.addEventListener('load', (e) => {
const box = document.querySelector('.box');
const rect = box.getBoundingClientRect();
document.addEventListener('mousemove', (e) => {
box.style.left = e.pageX + 'px';
box.style.top = e.pageY + 'px';
});
});
.box {
width: 50px;
height: 50px;
position:absolute;
transform:translate(-50%,-50%);
background-color: blue;
}
<div class="box"></div>
The transform: translate() property works relative to the size of the box but the left and top properties don't. It can also be much faster in some cases because in your code there was a lot of calculation going on. Whereas, this is straightforward.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With