Close Menu

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    How to make I love you heart card Animation in HTML CSS & JavaScript

    14 November 2025

    How to make Husky Dog Animation using HTML and CSS

    10 November 2025

    How to make 3D Login and Sign Up Form in HTML and CSS

    8 November 2025
    Facebook X (Twitter) Instagram YouTube Telegram Threads
    Coding StellaCoding Stella
    • Home
    • Blog
    • HTML & CSS
      • Login Form
    • JavaScript
    • Hire us!
    Coding StellaCoding Stella
    Home - JavaScript - How to make I love you heart card Animation in HTML CSS & JavaScript
    JavaScript

    How to make I love you heart card Animation in HTML CSS & JavaScript

    Coding StellaBy Coding Stella14 November 2025No Comments9 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Email WhatsApp Copy Link

    Let’s create an “I Love You” Heart Card Animation using HTML, CSS, and JavaScript. 💖
    This romantic and interactive project will feature a beautiful heart-shaped card that opens with a smooth animation and displays an “I Love You” message – perfect for Valentine’s Day or just to express love creatively through code.

    We’ll use:

    • HTML to structure the heart card and message.
    • CSS to style the heart, add glowing effects, and create smooth opening animations.
    • JavaScript to handle interactions, such as clicking to open the card or triggering heart animations.

    This project is ideal for beginners and intermediate developers who want to learn animation and interactivity in a fun, heartfelt way. Let’s get started and bring some love to life through code! 💌❤️

    HTML :

    This HTML code creates a cute “I Love You” interactive heart card. It loads external CSS and JS libraries, then builds a card with two sides that flip using CSS. Each side shows a heart shape made from simple divs and a small console.log('I Love You') code snippet for a coding aesthetic. The card has a “Click me” text and plays an audio file at the bottom. The page uses separate CSS (style.css) for design and animations, and JavaScript (script.js) for interactions, while Highlight.js styles the code snippet.

    <!DOCTYPE html>
    <html lang="en" >
    <head>
      <meta charset="UTF-8">
      <title>I love you heart card | @coding.stella</title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
    <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/atom-one-dark.min.css'><link rel="stylesheet" href="./style.css">
    
    </head>
    <body>
    
    <div class="content">
      <div id="background"></div>
      <div class="card-wrapper">
        <div class="card card-main">
          <div class="side side-a">
            <div class="back">
              <div class="heart">
                <div class="heart-half">
                  <div class="circle"></div>
                  <div class="rect"></div>
                </div>
                <pre class="ijustcode"><code class="language-javascript">&nbsp;&nbsp;console.log(
    &nbsp;&nbsp;&nbsp;&nbsp;'I Love You'
    &nbsp;&nbsp;);</code></pre>
              </div>
            </div>
            <div class="front">
              <div class="heart">
                <div class="heart-half">
                  <div class="circle"></div>
                  <div class="rect"></div>
                </div>
                <pre class="ijustcode"><code class="language-javascript">&nbsp;&nbsp;console.log(
    &nbsp;&nbsp;&nbsp;&nbsp;'I Love You'
    &nbsp;&nbsp;);</code></pre>
              </div>
            </div>
          </div>
          <div class="side side-b">
            <div class="back">
              <div class="heart">
                <div class="heart-half">
                  <div class="circle"></div>
                  <div class="rect"></div>
                </div>
                <pre class="ijustcode"><code class="language-javascript">&nbsp;&nbsp;console.log(
    &nbsp;&nbsp;&nbsp;&nbsp;'I Love You'
    &nbsp;&nbsp;);</code></pre>
                <div class="title">Click me</div>
              </div>
            </div>
            <div class="front">
              <div class="heart">
                <div class="heart-half">
                  <div class="circle"></div>
                  <div class="rect"></div>
                </div>
                <pre class="ijustcode"><code class="language-javascript">&nbsp;&nbsp;console.log(
    &nbsp;&nbsp;&nbsp;&nbsp;'I Love You'
    &nbsp;&nbsp;);</code></pre>
                <div class="title">Click me</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <audio controls="controls" src="https://toptrack-assets.s3.eu-central-1.amazonaws.com/i-just-called-comp.mp3">Your browser does not support the <audio> element</audio>
    </div>
    
    <script src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js'></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/granim/2.0.0/granim.min.js'></script><script  src="./script.js"></script>
    
    </body>
    </html>
    

    CSS :

    This CSS controls the layout, heart design, and flip animation of the card. It centers the card on the screen and sets the card to rotate in 3D when the wrapper gets the .active class. Each side of the card has a front and back that flip using rotateY. The heart shape is made using one circle and one rectangle rotated to form a heart, and their colors change when the card opens. Code snippets are styled with Highlight.js, and the “Click me” text is positioned on the heart. Confetti animations use keyframes to drop pieces from top to bottom with different speeds. The gradient, audio, and confetti stay behind the card using z-index. Overall, this CSS handles the flipping effect, heart shape, colors, and confetti animation.

    .content {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
    }
    
    .card-wrapper {
      width: 560px;
    }
    .card-wrapper .card {
      position: relative;
      width: 280px;
      height: 497.7777777778px;
      transform: perspective(1000px) translate(50%) scale(0.5) rotateY(0deg);
      transform-origin: 50px center;
      transition: 1s cubic-bezier(0, 0, 0, 0.94);
    }
    .card-wrapper .card .side {
      background: transparent;
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      transform: perspective(1000px) rotateY(0);
      transform-origin: right center;
      transform-style: preserve-3d;
      transition: 1s cubic-bezier(0, 0, 0, 0.94);
    }
    .card-wrapper .card .side.side-a {
      border-radius: 10px 0 0 10px;
    }
    .card-wrapper .card .side.side-b {
      border-radius: 10px 0 0 10px;
    }
    .card-wrapper .card .side .back,
    .card-wrapper .card .side .front {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      backface-visibility: hidden;
      transition: 0 0.5s cubic-bezier(0, 0, 0, 0.94);
      overflow: hidden;
    }
    .card-wrapper .card .side .front {
      z-index: 2;
      transform-origin: center;
    }
    .card-wrapper .card .side .back {
      transform: rotateY(180deg);
    }
    .card-wrapper .card .side .back .heart {
      transform: rotateY(180deg);
      max-height: 100%;
    }
    .card-wrapper .card .side.side-b .front .heart .circle,
    .card-wrapper .card .side.side-b .front .heart .rect {
      background: #f9bec7;
    }
    .card-wrapper .card .side.side-b .back .heart .title {
      display: none;
    }
    .card-wrapper.active .card {
      transform: perspective(1000px) translate(0%) scale(1) rotateY(0);
    }
    .card-wrapper.active .card .side.side-b {
      transform: perspective(1000px) rotateY(180deg);
    }
    .card-wrapper.active .card .side-a .front .heart .circle,
    .card-wrapper.active .card .side-a .front .heart .rect {
      background: #ff5c8a !important;
    }
    .card-wrapper.active .card .side-b .back .heart .circle,
    .card-wrapper.active .card .side-b .back .heart .rect {
      background: #ff5c8a !important;
    }
    .card-wrapper:not(.active) .heart {
      cursor: pointer;
    }
    
    .heart {
      font-family: "Satisfy", cursive;
    }
    .heart .heart-half {
      transform: rotate(-45deg) scale(0.8) translateX(23%) translateY(10%);
      transform-origin: 140px 140px;
    }
    .heart .heart-half .circle {
      width: 280px;
      height: 280px;
      background: red;
      border-radius: 50%;
      transition: background 1s cubic-bezier(0, 0, 0, 0.94);
    }
    .heart .heart-half .rect {
      width: 280px;
      height: 280px;
      background: red;
      margin-top: -140px;
      transition: background 1s cubic-bezier(0, 0, 0, 0.94);
    }
    .heart .title {
      position: absolute;
      top: 30%;
      font-family: "Quicksand", sans-serif;
      right: 10%;
      font-size: 38px;
      transform: rotate(45deg);
      color: #ff0a54;
    }
    
    .ijustcode {
      position: absolute;
      top: 124.4444444444px;
      right: 0;
      height: 100px;
      margin: auto;
      backface-visibility: hidden;
      transform: translateX(50%);
    }
    
    .side-b .ijustcode code {
      transform: rotateY(-180deg);
    }
    .side-b .front .ijustcode {
      display: none;
    }
    
    .hljs-addition, .hljs-attribute, .hljs-meta .hljs-string, .hljs-regexp, .hljs-string {
      color: #c379ba;
      font-weight: 600;
    }
    
    pre code.hljs {
      border-radius: 10px;
    }
    
    audio {
      display: none;
    }
    
    /*******
    ********
    
    Confeti styles
    
    ********
    *******/
    @keyframes confetti-slow {
      0% {
        transform: translate3d(0, 0, 0) rotateX(0) rotateY(0);
      }
      100% {
        transform: translate3d(25px, 105vh, 0) rotateX(360deg) rotateY(180deg);
      }
    }
    @keyframes confetti-medium {
      0% {
        transform: translate3d(0, 0, 0) rotateX(0) rotateY(0);
      }
      100% {
        transform: translate3d(100px, 105vh, 0) rotateX(100deg) rotateY(360deg);
      }
    }
    @keyframes confetti-fast {
      0% {
        transform: translate3d(0, 0, 0) rotateX(0) rotateY(0);
      }
      100% {
        transform: translate3d(-50px, 105vh, 0) rotateX(10deg) rotateY(250deg);
      }
    }
    .container {
      /*width: 100vw;
      height: 100vh;
      background: #f0f0f0;*/
    }
    
    .confetti-container {
      perspective: 700px;
      position: absolute;
      overflow: hidden;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: -1;
    }
    
    .confetti {
      position: absolute;
      z-index: 1;
      top: -10px;
      border-radius: 0%;
    }
    
    .confetti-animation-slow {
      animation: confetti-slow 2.5s linear 1 forwards;
    }
    
    .confetti-animation-medium {
      animation: confetti-medium 2s linear 1 forwards;
    }
    
    .confetti-animation-fast {
      animation: confetti-fast 1.5s linear 1 forwards;
    }
    
    #gradient {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100vw;
      height: 100vh;
      z-index: -2;
      opacity: 0;
      transition: opacity 1s cubic-bezier(0, 0, 0, 0.94);
    }

    JavaScript:

    This JavaScript powers the whole interaction: it highlights the code using Highlight.js, creates a Confetti class that generates falling confetti pieces with random colors, sizes, and speeds, and starts/stops them when the card is clicked. When you click the card, it toggles the “active” class, plays/pauses the audio, fades the gradient, and shows/hides confetti. It also adds a 3D hover effect by rotating the card based on mouse position. Finally, it uses Granim.js to create a smooth animated gradient in the background. All functions together handle confetti creation, card flipping, sound, hover animation, and background effects.

    (function () {
    
      hljs.highlightAll();
    
      var Confetti = function (options) {
        var t = this;
        t.o = options || {};
    
    
        //DOM storage
        t.doms = {};
    
        //Vars storage
        t.vars = {
          confettiFrequency: 3, //DEP???
          confettiColors: ['#fce18a', '#ff726d', '#b48def', '#f4306d'],
          confettiSpeed: ['slow', 'medium', 'fast'],
          confetiCount: 0,
          confetiLimit: 100,
          confettiDestroyTime: 3000, //ms
          confettiRenderTime: 60, //ms
          confettiSizeRange: [3, 7] };
    
    
        //classes store
        t.classes = {
          'confettiContainer': 'confetti-container' };
    
    
        //callbacks store
        t.callbacks = {};
    
        //Init if options are valid
        if (t.handleOptions()) {
          t.init();
        }
    
      };
    
    
    
      Confetti.prototype.handleOptions = function () {
        var t = this;
    
        if (t.o.target) {
          t.doms.target = t.o.target;
        } else {
          throw 'Confetti.options.target - is not valid DOM element';
          return false;
        }
    
        if (!!t.o.onstart) {
          t.callbacks.onstart = t.o.onstart;
        }
    
        if (!!t.o.ondone) {
          t.callbacks.ondone = t.o.ondone;
        }
    
        return true;
      };
    
      Confetti.prototype.setupElements = function () {
        var t = this,
        containerDOM = document.createElement('div'),
        targetPosition = t.doms.target.style.position;
    
        containerDOM.className = t.classes['confettiContainer'];
    
        if (targetPosition != 'relative' || targetPosition != 'absolute') {
          t.doms.target.style.position = 'relative';
        }
    
        t.doms.target.appendChild(containerDOM);
        t.doms.containerDOM = containerDOM;
      };
    
      Confetti.prototype.getContainerSize = function () {
        var t = this;
    
        return Math.floor(Math.random() * t.vars.confettiSizeRange[0]) + t.vars.confettiSizeRange[1] + 'px';
      };
    
      Confetti.prototype.getConfettiColor = function () {
        var t = this;
    
        return t.vars.confettiColors[Math.floor(Math.random() * t.vars.confettiColors.length)];
      };
    
    
      Confetti.prototype.getConfettiSpeed = function () {
        var t = this;
    
        return t.vars.confettiSpeed[Math.floor(Math.random() * t.vars.confettiSpeed.length)];
      };
    
    
      Confetti.prototype.getConfettiPosition = function () {
        var t = this;
    
        return Math.floor(Math.random() * t.doms.target.offsetWidth) + 'px';
      };
    
      Confetti.prototype.generateConfetti = function () {var _confettiDOM$classLis, _confettiDOM$classLis2;
        var t = this,
        confettiDOM = document.createElement('div'),
        confettiSize = t.getContainerSize(),
        confettiBackground = t.getConfettiColor(),
        confettiLeft = t.getConfettiPosition(),
        confettiSpeed = t.getConfettiSpeed();
    
        confettiDOM === null || confettiDOM === void 0 ? void 0 : (_confettiDOM$classLis = confettiDOM.classList) === null || _confettiDOM$classLis === void 0 ? void 0 : _confettiDOM$classLis.add('confetti');
        confettiDOM === null || confettiDOM === void 0 ? void 0 : (_confettiDOM$classLis2 = confettiDOM.classList) === null || _confettiDOM$classLis2 === void 0 ? void 0 : _confettiDOM$classLis2.add('confetti-animation-' + confettiSpeed);
        confettiDOM.style.left = confettiLeft;
        confettiDOM.style.width = confettiSize;
        confettiDOM.style.height = confettiSize;
        confettiDOM.style.backgroundColor = confettiBackground;
    
        confettiDOM.removeTimeout = setTimeout(function () {
          confettiDOM.parentNode.removeChild(confettiDOM);
        }, t.vars.confettiDestroyTime);
    
        t.doms.containerDOM.appendChild(confettiDOM);
      };
    
      Confetti.prototype.renderConfetti = function () {
        var t = this;
    
        if (t.callbacks.onstart) {
          t.callbacks.onstart();
        }
    
        t.confettiInterval = setInterval(function () {
          t.vars.confetiCount++;
    
          if (t.vars.confetiCount > t.vars.confetiLimit) {
            if (t.callbacks.ondone) {
              t.callbacks.ondone();
            }
            clearInterval(t.confettiInterval);
            return false;
          } else {
            t.generateConfetti();
          }
    
    
        }, t.vars.confettiRenderTime);
      };
    
      Confetti.prototype.restart = function (instance) {
        var t = this || instance;
        t.vars.confetiCount = 0;
        t.renderConfetti();
      };
    
      Confetti.prototype.start = Confetti.prototype.restart;
    
      Confetti.prototype.stop = function () {
        var t = this || instance;
        t.vars.confetiCount = t.vars.confetiLimit;
      };
    
    
      Confetti.prototype.init = function () {
        var t = this;
    
        t.setupElements();
      };
    
    
      const content = document.querySelector('.content');
      const gradient = document.querySelector('#background');
      const cardWrapper = document.querySelector('.card-wrapper');
      const audio = document.querySelector('audio');
      const confetti = new Confetti({ target: content });
    
      cardWrapper.addEventListener('click', () => {
        const isActive = cardWrapper.classList.contains('active');
    
        if (isActive) {
          cardWrapper.classList.remove('active');
          audio.pause();
          confetti.stop();
          gradient.style.opacity = 0;
        } else {
          cardWrapper.classList.add('active');
          audio.play();
          confetti.start();
          gradient.style.opacity = 1;
        }
      });
    
    
      //  https://codesandbox.io/s/3d-hover-effect-hqy6h?file=/src/index.js:0-944
      const card = cardWrapper;
      const motionMatchMedia = window.matchMedia("(prefers-reduced-motion)");
      const THRESHOLD = 30;
    
      function handleHover(e) {
        const { clientX, clientY, currentTarget } = e;
        const { clientWidth, clientHeight, offsetLeft, offsetTop } = currentTarget;
    
        const horizontal = (clientX - offsetLeft) / clientWidth;
        const vertical = (clientY - offsetTop) / clientHeight;
        const rotateX = (THRESHOLD / 2 - horizontal * THRESHOLD).toFixed(2);
        const rotateY = (vertical * THRESHOLD - THRESHOLD / 2).toFixed(2);
    
        card.style.transform = `perspective(${clientWidth}px) rotateX(${rotateY}deg) rotateY(${rotateX}deg) scale3d(1, 1, 1)`;
      }
    
      function resetStyles(e) {
        card.style.transform = `perspective(${e.currentTarget.clientWidth}px) rotateX(0deg) rotateY(0deg)`;
      }
    
      if (!motionMatchMedia.matches) {
        card.addEventListener("mousemove", handleHover);
        card.addEventListener("mouseleave", resetStyles);
      }
    
    
      new Granim({
        element: '#gradient',
        direction: 'radial',
        isPausedWhenNotInView: true,
        states: {
          "default-state": {
            gradients: [
            ['#ff8faf', '#ffe5ed'],
            ['#f38fff', '#ffe5ed'],
            ['#ff8f8f', '#ffe5ed']] } } });
    
    
    
    
    })();

    In conclusion, building an “I Love You” Heart Card Animation using HTML, CSS, and JavaScript is a fun and creative way to learn interactive web design. With just a few lines of code, we combined structure, styling, and animation to create something expressive and meaningful.

    If you run into any problems with your project, worry not. The remedy is just a click away – Download the source code and confront your coding challenges with enthusiasm. Enjoy your coding adventure!

    Animation CSS Animation
    Share. Copy Link Twitter Facebook LinkedIn Email WhatsApp
    Previous ArticleHow to make Husky Dog Animation using HTML and CSS
    Coding Stella
    • Website

    Related Posts

    HTML & CSS

    How to make Husky Dog Animation using HTML and CSS

    10 November 2025
    HTML & CSS

    How to make Animated Search Bar Input using HTML and CSS

    5 November 2025
    JavaScript

    How to make Magic Navigation Tabs Menu using HTML CSS & JavaScript

    2 November 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Trending Post

    Master Frontend in 100 Days Ebook

    2 March 202430K Views

    How to make Modern Login Form using HTML & CSS | Glassmorphism

    11 January 202428K Views

    How to make I love you Animation in HTML CSS & JavaScript

    14 February 202422K Views

    How to make Valentine’s Day Card using HTML & CSS

    13 February 202414K Views
    Follow Us
    • Instagram
    • Facebook
    • YouTube
    • Twitter
    ads
    Featured Post

    How to make Glowing Animated Login Form using HTML & CSS

    25 February 2025

    Best Programming Languages for Web Development

    25 January 2024

    Why is JavaScript So Popular in Web Development?

    25 January 2024

    How to make Magic Navigation Tabs Menu using HTML CSS & JavaScript

    2 November 2025
    Latest Post

    How to make I love you heart card Animation in HTML CSS & JavaScript

    14 November 2025

    How to make Husky Dog Animation using HTML and CSS

    10 November 2025

    How to make 3D Login and Sign Up Form in HTML and CSS

    8 November 2025

    How to make Animated Search Bar Input using HTML and CSS

    5 November 2025
    Facebook X (Twitter) Instagram YouTube
    • About Us
    • Privacy Policy
    • Return and Refund Policy
    • Terms and Conditions
    • Contact Us
    • Buy me a coffee
    © 2025 Coding Stella. Made with 💙 by @coding.stella

    Type above and press Enter to search. Press Esc to cancel.

    Ad Blocker Enabled!
    Ad Blocker Enabled!
    Looks like you're using an ad blocker. We rely on advertising to help fund our site.
    Okay! I understood