Skip to main content
<CodeWithBhurtel/>
HomeLearnProjectsChallengesBlogAboutContactLogin
<CodeWithBhurtel/>

Learn through structured lessons, real projects, and live challenges. Free tutorials for HTML, CSS, JavaScript, and more.

Pages

  • Home
  • Learn
  • Blog
  • Projects
  • Challenges
  • About
  • Contact

Lessons

  • HTML
  • CSS
  • JavaScript

© 2026 CodeWithBhurtel. All rights reserved.

Privacy PolicyTerms & Conditions
Projects

Love Heart Animation

IntermediateHTML, CSS, JavaScript

This sits at a beginner to intermediate level. The JavaScript portion is genuinely simple, just a loop that creates elements and sets one custom property on each.

Love Heart Animation – project preview
Share this project
Follow me on social media

About this project

This project renders a heart-shaped animation made entirely out of the phrase "I love you," repeated a hundred times and set in continuous motion against a black background. Every instance is generated through JavaScript and animated purely with CSS, without any external animation library, canvas, or SVG involved. The result is a soft, glowing trail of text that loops endlessly and traces the outline of a heart, which makes it a good project for anyone who wants to see how far plain CSS keyframes can be pushed before reaching for a heavier tool. The core idea behind the animation is combining two separate motion systems on the same element. One layer handles horizontal movement using a simple back and forth translation, while the other layer handles vertical movement through a long, carefully plotted keyframe sequence that bends the straight vertical motion into the curved shape of a heart. Each of the hundred elements gets a slightly different animation delay based on its index, calculated directly in CSS using a custom property. That staggering is what turns a hundred identical elements into what looks like a single flowing stream of text rather than a hundred things blinking in place.

What you will learn

Working through this project teaches you how to generate repeated DOM elements dynamically with JavaScript instead of hardcoding them in HTML, which is a habit worth building early since almost no real animation with dozens or hundreds of elements is written by hand. You will also learn how to use CSS custom properties, specifically the --i variable, to pass a unique value into each element and then use that value inside a calc() expression to offset animation timing. This single technique, staggering delays through a custom property, is one of the most reusable tricks in CSS animation and shows up constantly in more advanced motion design work. Beyond that, the project is a strong introduction to layered animation, where two different keyframe animations run on nested elements at the same time to produce a shape that neither animation could create on its own. Plotting the vertical keyframes also gives you a feel for how percentage-based keyframes work in practice, since the heart shape only emerges because of very specific percentage stops rather than a simple linear motion. If you have never manually plotted a curved path using keyframe percentages before, this project is a good hands-on introduction to that process.

Understand the code

Read a plain-language overview or a file-by-file breakdown. Ask questions about the project below the overview.

This project creates a dynamic web animation featuring the phrase "I love you" that moves along a path resembling a heart. Multiple instances of the text are displayed, each following the heart shape with a staggered timing, resulting in a continuous, flowing visual effect against a dark background.

The script.js file is responsible for programmatically generating the elements that will be animated. It iterates 100 times, creating a div element for each instance of the "I love you" text. Crucially, it assigns a unique custom CSS property, --i, to each of these elements, which acts as an index for controlling their individual animation timings.

for (let i = 1; i <= totalItems; i++) {
  const love = document.createElement("div");
  love.className = "love";
  love.style.setProperty("--i", i); // Assigns a unique index
  // ... further element creation ...
  ui.appendChild(love);
}

This JavaScript loop dynamically creates 100 "love" elements and assigns a unique --i custom property to each, which is essential for staggering their animations.

The style.css file defines the visual appearance and the complex motion of the animation. It styles the "I love you" text and positions each instance absolutely on the page. The core of the movement is achieved through two keyframe animations: @keyframes horizontal for side-to-side motion and @keyframes vertical for the intricate up-and-down path that forms the heart shape.

@keyframes vertical {
  0% { transform: translateY(180px); }
  10% { transform: translateY(45px); }
  /* ... many more keyframes ... */
  100% { transform: translateY(180px); }
}

This CSS keyframe animation defines the precise vertical movement that, when combined with horizontal motion, traces the heart shape.

The staggered effect, where each "I love you" text appears to follow the one before it, is achieved by combining the JavaScript-assigned --i custom property with CSS animation-delay. Each love element's animation start time is offset by calc(var(--i) * -300ms), meaning subsequent elements effectively start earlier in their animation cycle. This creates the illusion of a continuous flow of words tracing the heart path.

#ui .love_horizontal {
  animation: horizontal 10s infinite alternate ease-in-out;
  animation-delay: calc(var(--i) * -300ms); /* Staggers animation start */
}

This CSS rule applies the horizontal animation and uses the --i custom property to calculate a negative animation-delay, causing each "love" element to start its animation at a different point in time.

Ask about this project

Have a question about how this project works? Ask below and get an answer based on the project code.

Code Breakdown

Structured technical breakdown for beginners.

No breakdown yet. Generate one to see a file-by-file explanation.

Comments

No comments yet. Sign in to leave a comment.

Sign in to leave a comment.