Animate an Object Movement with HTML/CSS/JS

Banner for a MediaJam post

Eugene Musebe


JavaScript frameworks can be used to move a number of DOM elements, or any other HTML element) around the page according to some sort of pattern determined by a logical equation or function. In this article, we demonstrate how to implement such a function


Check the sandbox demo on Codesandbox.

You can also get the project github repo using Github.


Entry-level javascript and React/Nextjs knowledge.

Setting Up the Sample Project

In your respective folder, create a new net js app using npx create-next-app animate in your terminal. Head to your project root directory cd animate

We will begin by setting up Cloudinary integration for our next js backend. We will it to configure the cloudinary media file upload procedure.

Create your own cloudinary account using Link and log into it. Each cloudinary user account will have a dashboard containing environmental variable keys that are necessary for the cloudinary integration in our project.

In your project directory, start by including Cloudinary in your project dependencies npm install cloudinary create a new file named .env.local and paste the following code. Fill the blanks with your environment variables from the cloudinary dashboard using the following guide.


Restart your project: npm run dev.

In the pages/api folder, create a new file named upload.js. Start by configuring Cloudinary environment keys and libraries.

2var cloudinary = require("cloudinary").v2;
5 cloud_name: process.env.CLOUDINARY_NAME,
6 api_key: process.env.CLOUDINARY_API_KEY,
7 api_secret: process.env.CLOUDINARY_API_SECRET,

Create a handler function to execute the POST request. The function will receive captioned media file data and post it to the cloudinary website. It then captures the media file's cloudinary link and sends it back as a response.

3export default async function handler(req, res) {
4 if (req.method === "POST") {
5 let url = ""
6 try {
7 let fileStr =;
8 const uploadedResponse = await cloudinary.uploader.upload_large(
9 fileStr,
10 {
11 resource_type: "video",
12 chunk_size: 6000000,
13 }
14 );
15 url = uploadedResponse.url
16 } catch (error) {
17 res.status(500).json({ error: "Something wrong" });
18 }
20 res.status(200).json({data: url});
21 }

The code above concludes our backend.

In our front end, we will demonstrate how to animate html divs and the result will demonstrate a moving vehicle. Start by using the following code in your return statement. All animations will be implemented from our css file while the js code will implement cloudinary integration.

The code below will contain a navbar containing the project title, a caption button, and a hidden link text which will only show up once the link is available from the backend.

4 return (
5 <>
6 <nav>
7 <h2>Animate a javascript object movement</h2>
8 {link && <a href={link}>captioneLink</a>}
9 <button onClick={uploadHandler}>Caption</button>
10 </nav>
11 <div className="country-wrap" ref={captionRef}>
12 <div className="sun"></div>
13 <div className="grass"></div>
14 <div className="street">
15 <div className="car">
16 <div className="car-body">
17 <div className="car-top-back">
18 <div className="back-curve"></div>
19 </div>
20 <div className="car-gate"></div>
21 <div className="car-top-front">
22 <div className="wind-sheild"></div>
23 </div>
24 <div className="bonet-front"></div>
25 <div className="stepney"></div>
26 </div>
27 <div className="boundary-tyre-cover">
28 <div className="boundary-tyre-cover-back-bottom"></div>
29 <div className="boundary-tyre-cover-inner"></div>
30 </div>
31 <div className="tyre-cover-front">
32 <div className="boundary-tyre-cover-inner-front"></div>
33 </div>
34 <div className="base-axcel"></div>
35 <div className="front-bumper"></div>
36 <div className="tyre">
37 <div className="gap"></div>
38 </div>
39 <div className="tyre front">
40 <div className="gap"></div>
41 </div>
42 <div className="car-shadow"></div>
43 </div>
44 </div>
45 <div className="street-stripe"></div>
46 <div className="hill"></div>
47 </div>
48 </>

The code below is the css code for the animation. It is quite lengthy and yet easily comprehendible. I'd suggest playing with the code one div container at a time using the style below to get a clearer picture of the animation. In this documentation, i'll show the car tires css code just to share an idea of how the animation works:

3.tyre {
4 width: 30px;
5 height: 30px;
6 border-radius: 50%;
7 background: #3f3f40;
8 position: absolute;
9 z-index: 2;
10 left: 9px;
11 top: 20px;
12 -moz-animation: tyre-rotate 1s infinite linear;
13 -webkit-animation: tyre-rotate 1s infinite linear;
15@-moz-keyframes tyre-rotate {
16 from {
17 -moz-transform: rotate(-360deg);
18 }
19 to {
20 -moz-transform: rotate(0deg);
21 }
23@-webkit-keyframes tyre-rotate {
24 from {
25 -webkit-transform: rotate(-360deg);
26 }
27 to {
28 -webkit-transform: rotate(0deg);
29 }
31.tyre:before {
32 content: "";
33 width: 20px;
34 height: 20px;
35 border-radius: 50%;
36 background: #bdc2bd;
37 position: absolute;
38 top: 5px;
39 left: 5px;
40} {
42 background: #3f3f40;
43 width: 2px;
44 height: 4px;
45 position: absolute;
46 left: 14px;
47 top: 8px;
48 box-shadow: 0 9px 0 #3f3f40;
49} {
51 content: "";
52 display: block;
53 width: 2px;
54 height: 4px;
55 position: absolute;
56 background: #3f3f40;
57 box-shadow: 0 12px 0 #3f3f40;
58 -webkit-transform: rotate(-90deg);
59 -webkit-transform-origin: 0 7px;
60 -moz-transform: rotate(-90deg);
61 -moz-transform-origin: 0 7px;
62 z-index: 3;
65.tyre.front {
66 left: 94px;

The animation will rotate the gap inside the tires to animate a moving tire as the car pushes forward. The cars' animation is the lengthiest but still easy to understand. You can use the github repo to locate them.

Once you are comfortable with the animation, use the following code to caption your result. We use html2canvas to capture a result and send it to the backend as a base64 string. The result will be the captioned media file's Cloudinary link which will be shown to the user using the setLink state hook.

Well done. You can now go over the article and enjoy your coding experience. The result from my code will look like below:

final UI

Enjoy the experience.

Eugene Musebe

Software Developer

I’m a full-stack software developer, content creator, and tech community builder based in Nairobi, Kenya. I am addicted to learning new technologies and loves working with like-minded people.