I was surfing the web the other day when I came across lightning js. An open source project for creating animated UIs with webGL. It’s mainly used for TV apps and has great performance of low-spec devices. It’s fast. lightning fast. A demo on their landing page caught my eyes. I’m UI lover so I decided to give it a try and recreate it using JS and CSS very quickly.


First I started by capturing the controls. Mouse X and Y. You can easily get it by writing a mousemove event handler. It comes as clientX and clientY. This is how you can destructure it from the event (e):

Next we just need to capture the size of the window to get a proportional position of the mouse pointer in terms of width and height of the window.

1
2
3
4
5
6
7
8
document.addEventListener('mousemove', (e) => {
    const { clientX, clientY } = e;
    const { clientWidth, clientHeight } = document.body;
    const ratio = {
        x: (clientX - clientWidth / 2) / clientWidth,
        y: (clientY - clientHeight / 2) / clientHeight
    };
})

Ok, for the effect itself there could be multiple ways to do it. But I thought the most straightforward way would be to create a wrapper for each image that shows a say 80% of the whole image. This way we can move the remaining 10% of each side by the ratios of the control. We can then apply transform values to each image. To give it a better feel that images have a depth I also added an inset box-shadow to the wrapper which is in sync with the translate values.

1
2
image.style.transform = `translateX(${translateX}px) ...`;
image.parentElement.style.boxShadow = `inset ${translateX}px ...`;

Finally, we just need to rotate the whole container by giving it a perspective transform and set rotateX and rotateY values.

1
container.style.transform = `perspective(${perspective}px) rotateY(...`;

It was a funny process to find which way the elements should move and rotate and determine whether the X and Y values must be positive relative to the ratio or negative. I figured it out at the end in a brute force manner as every busy programmer would do 🤦. This was a quick and fun exercise in using JS and CSS to create interactive animations. Lightning JS is a great library for this, but it’s always good to understand the underlying code to create something similar from scratch.