DEV Community

Cover image for Create a parallax effect when the mouse moves
Clément Gaudinière
Clément Gaudinière

Posted on

Create a parallax effect when the mouse moves

Animated and interactive pages attract more and more attention from users. For this, we can use complex animations, or others simpler as parallaxes. There are two types of parallaxes: those that are activated when the page is scrolled, and others that are animated when the mouse is moved. Today we will see how to create a parallax effect when moving the mouse in javascript vanilla.


Setting up in HTML

The HTML structure will be relatively simple. We will use a main div, containing several spans, corresponding to animated balls when moving the mouse around a main title. Here is the HTML:

<div class="parallax-wrap">
  <span value="-15"></span>
  <span value="5"></span>
  <span value="30"></span>
  <span value="-5"></span>
  <span value="15"></span>
  <h2>Parallax effect</h2>
</div>
Enter fullscreen mode Exit fullscreen mode

Setting up the CSS

Concerning the CSS, nothing new, we will use only basic features of the language.
It is important to set overflow to hidden in the body, otherwise the animated balls will create a scroll of the page.
The span must be in position: absolute;, and have a border-radius of 100%, in order to create circular blocks.
Then we set each span one by one, by defining a color, a z-index, and its position. Here is the CSS (you can see the SCSS code in the codepen at the end) :

body {
  margin: 0;
  height: 100vh;
  background-color: #bd1060;
  overflow: hidden;
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
}
.parallax-wrap {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
}
.parallax-wrap h2 {
  position: relative;
  font-size: 100px;
  color: white;
  z-index: 2;
  text-align: center;
}
.parallax-wrap span {
  position: absolute;
  height: 20px;
  width: 20px;
  border-radius: 100%;
}
.parallax-wrap span:nth-child(1) {
  top: 70%;
  left: 70%;
  background: blue;
  z-index: 3;
}
.parallax-wrap span:nth-child(2) {
  top: 60%;
  left: 80%;
  background: yellow;
  z-index: 3;
}
.parallax-wrap span:nth-child(3) {
  top: 40%;
  left: 60%;
  background: green;
  z-index: 3;
}
.parallax-wrap span:nth-child(4) {
  top: 70%;
  left: 40%;
  background: red;
  z-index: 3;
}
.parallax-wrap span:nth-child(5) {
  top: 40%;
  left: 30%;
  background: purple;
  z-index: 3;
}
Enter fullscreen mode Exit fullscreen mode

Setting up the JS

First of all we have to detect when the user moves his mouse, with line 1. Then we trigger a parallax function, which selects all the spans contained in our main container. Then we animate them as it should be. The Javascript code:

document.addEventListener("mousemove", parallax);
function parallax(event) {
  this.querySelectorAll(".parallax-wrap span").forEach((shift) => {
    const position = shift.getAttribute("value");
    const x = (window.innerWidth - event.pageX * position) / 90;
    const y = (window.innerHeight - event.pageY * position) / 90;

    shift.style.transform = `translateX(${x}px) translateY(${y}px)`;
  });
}
Enter fullscreen mode Exit fullscreen mode

Final result

Here is the final result. You can of course modify the elements, to replace them, for example, by images. You can also modify the value in the HTML span, so that the parallax effect is amplified.


I hope you learned something about parallaxes, feel free to ask me any questions you may have. 👍


You want to support me ?

Buymeacoffee

OR

Patreon

Top comments (8)

Collapse
 
loucyx profile image
Lou Cyx

Instead of using shift.style.transform and updating the style in every single element, ideally you should use CSS Custom Properties and use CSS more heavily, this way the performance is way better and you only update the parent element. Here's a demo with that approach:

Cheers!

Collapse
 
clementgaudiniere profile image
Clément Gaudinière

I did not know, indeed it is better.

Collapse
 
cheestudio profile image
Lars Faye

You're both incredible! This was so applicable to what I needed to do!

Both methods have merit, and your original approach I think is more understandable in a way, but Luke's method does make sense from a performance perspective, and that we're relegating the languages to their proper jobs (JS for DOM interactive, CSS for element presentation/animation).

Thank you both! 🙌🏻

Collapse
 
roartex profile image
Rory

After doing a bunch of testing with a large amount of elements (SVG and PNG), the original article's solution performs a lot better for me in macOS Chrome, Safari and Firefox. With 250 elements all with varying shift parameters, the original solution that applies transform properties directly into the DOM performs around 2-3x faster versus the CSS custom properties approach.

Collapse
 
coderlifeisawesome profile image
lifeascoder

It is great Never knew about mouse parallax scrolling.

Collapse
 
clementgaudiniere profile image
Clément Gaudinière

Thanks !

Collapse
 
andrewbaisden profile image
Andrew Baisden

Cool!

Collapse
 
jjjjcccjjf profile image
endan

This is very helpful, thank you so much!