profile picture of Olivier Larose

Olivier Larose

May 7, 2023

/

Beginner

/

Medium

Pixel Cursor Trailing

How to create a cursor pixel trailing effect with React

A pixel trailing effect created with React. As the cursor moves, squares are created along the mouse to create an effect of trailing. Made with React and Next.js

Live DemoSource codeVideo Tutorial
background video

Initializing the project

Let's start the project by creating a Next.js application. We can do that by running npx create-next-app@latest client inside of a terminal.

Adding the HTML and CSS

We can delete everything in the page.js , global.css and page.module.css and add our own HTML and CSS, to start with a nice blank application.

For the CSS, we're going to use CSS Module, so make sure to create a Home.module.css file inside of the styles folder. Thankfully, Next.js has built-in support for CSS Modules

page.js

page.mod...

1

'use client'

2

import styles from './page.module.css'

3

4

export default function Home() {

5

6

return (

7

<div className={styles.container}>

8

<div className={styles.body}>

9

<p>We specialize in turning space into complexe shapes</p>

10

</div>

11

</div>

12

)

13

}

14

15

We should have something like this:

Screenshot of the HTML and CSS results

Rendering the blocks

Now that we've added the basic layout, we'll create a series of blocks in HTML that will allow us to create the trailing effect.

  • We will create blocks of 5vw x 5vw of height.
  • We will have 20 columns on the horizontal with a certain amount of blocks inside of them.
  • To calculate the amount of blocks inside the columns, we will do Math.ceil(window.innerHeight / 5vw)

Storing the Windows width inside the state

Since the creating of the blocks require the value of the windows width, we will initially store it inside the state.

page.js

1

'use client'

2

import styles from './page.module.css'

3

import { useState, useEffect } from 'react';

4

5

export default function Home() {

6

7

const [windowsWidth, setWindowsWidth] = useState(0);

8

9

useEffect(() => {

10

setWindowsWidth(window.innerWidth);

11

}, [])

12

13

return (

14

<div className={styles.container}>

15

<div className={styles.body}>

16

<p>We specialize in turning space into complexe shapes</p>

17

</div>

18

</div>

19

)

20

}

21

  • Note that if you are not using Next.js, and you are using something like Vanilla React or any other Client-side tool, you do not need to store the value of the window inside the state.

Rendering the different blocks

Once we have stored the windows width inside the state, we can now use it to render the blocks.

page.js

Home.mod...

1

...

2

const [windowsWidth, setWindowsWidth] = useState(0);

3

4

const getBlocks = () => {

5

const blockSize = windowsWidth * 0.05;

6

const nbOfBlocks = Math.ceil(window.innerHeight / blockSize);

7

return [...Array(nbOfBlocks).keys()].map((_, index) => {

8

return <div key={index}></div>

9

})

10

}

11

return (

12

<div className={styles.container}>

13

...

14

<div className={styles.grid}>

15

{

16

windowsWidth > 0 && [...Array(20).keys()].map( (_, index) => {

17

return <div key={'b_' + index} className={styles.column}>

18

{

19

getBlocks()

20

}

21

</div>

22

})

23

}

24

</div>

25

</div>

26

)

27

Here's a couple of important things to note:

  • Line 16: 20 columns are rendered.
  • Line 7: Each column contains a nbOfBlocks depending on the windows height and the windows width.
Screenshot of the HTML and CSS results

Creating the trail

Now that we have all the blocks, we can simply add a mouse event listener to create thet trail.

page.js

page.mod...

1

...

2

3

const getBlocks = () => {

4

const blockSize = windowsWidth * 0.05;

5

const nbOfBlocks = Math.ceil(window.innerHeight / blockSize);

6

return [...Array(nbOfBlocks).keys()].map((_, index) => {

7

return <div onMouseEnter={(e) => {colorize(e.target)}} key={index}></div>

8

})

9

}

10

11

const colorize = (el) => {

12

el.style.backgroundColor = 'black'

13

setTimeout( () => {

14

el.style.backgroundColor = 'transparent';

15

}, 300)

16

}

17

18

...
  • Nothing too complicated here. If we hover a block, we set the background-color to black and after .3s we reset it to transparent.

Mixing in blend modes

For a final touch, we'll add a blending mode to the text so to have a nice color effect. Thankfully, CSS is extremely powerful for that and will allow us to create this very easily with the mix-blend-mode property.

page.module.css

1

...

2

3

.container .body{

4

...

5

text-transform: uppercase;

6

mix-blend-mode: difference;

7

color: white;

8

}

9

Wrapping up

That was it for this animation, very fun to see how we can use simple HTML and css to create a trailing effect that looks pixelated.

Hope you learned a lot :)

-Oli

Related Animations

image

June 2, 2024

Mouse Image Distortion

A website animation featuring an image distortion in a curved, using the sin function, React, React Three Fiber and Framer Motion

image

May 4, 2024

Paint Reveal

A website tutorial on making a paint reveal / erasing effect using the destination out blend mode of the canvas API, made with React and Next.js

image

March 8, 2024

Blend Mode Cursor

A website tutorial featuring a moving cursor on mouse move, colored with CSS blend mode difference, made with React and GSAP. Inspired by https://trionn.com/