JavaScript: Raining Hearts

By Xah Lee. Date: . Last updated: .

This page shows you how to use JavaScript to create a “raining hearts” or “falling snow” effect.

Here is the JavaScript code:

// 2014-08-18
// 2019-09-30
// copyright 2014, 2019-09-30 Xah Lee
// feel free to use, but must give credit, link back to this page
// from http://xahlee.info/js/js_raining_hearts.html

{

    const num_of_hearts = 30;
    const driftX = 50;
    const gravity = 100;
    const update_speed = 900; // millisecond

    // const heartTypes= [... "♥💕💓💔💖💗💘💝💞💟💙💚💛💜" ];
    const heartTypes= [... "💔♥" ];

    const viewportWidth = document.documentElement.clientWidth;
    const viewportHeight = document.documentElement.clientHeight;

    const viewSpaceWidth = viewportWidth+50;
    const viewSpaceHeight = viewportHeight+50;

    const randomInt = ((xmin,xmax) => (Math.floor( Math.random() * (xmax + 1 - xmin) + xmin )));

    const randomReal = ((xmin,xmax) => ( Math.random() * (xmax - xmin) + xmin ));

    const randomColor = (() => ("hsla" + "(" + randomInt(0,360) + "," +
                                randomInt(70,100) + "%," +
                                randomInt(40,60) + "%," +
                                randomReal(.8,1) + ")" ) );

    const f_restart_heart = ((xx) => {
        xx["xxleft"]=randomInt(0, viewSpaceWidth);
        xx.style.left= xx["xxleft"] + "px";
        xx["xxtop"]=randomInt(0, viewSpaceHeight) - viewSpaceHeight;
        xx.style.top= xx["xxtop"] + "px";
        xx["xrotate"] = randomInt(-150, 150);
        xx.style.transform = "rotate(" + xx["xrotate"] + "deg)";
    });

    const heart_box = document.createElement("div");
    heart_box.setAttribute("id","heart_box");

    const f_new_heart = (() => {
        const yy = document.createElement("div");
        yy. textContent= heartTypes[Math.floor( Math.random() * heartTypes.length )];
        yy["xxleft"]=randomInt(0, viewSpaceWidth);
        yy.style.left= yy["xxleft"] + "px";
        yy["xxtop"]= -90;
        yy.style.top= yy["xxtop"] + "px";
        yy["xrotate"] = randomInt(-150, 150);
        yy.style.transform = "rotate(" + yy["xrotate"] + "deg)";
        yy.style.color = randomColor();
        yy["xsize"]= 10 + randomInt(0,30);
        yy.style.fontSize = yy["xsize"] + "px";

        yy.style.position="fixed";
        yy.style.zIndex= randomInt(100,9999) .toString();
        yy.style.transition= "top linear 1.5s, left linear 1.5s, transform linear 1.5s";
        // f_restart_heart(yy);
        return yy;
    });

    { for (let i=0; i < num_of_hearts; i++) { heart_box.appendChild( f_new_heart()) } } ;

    document.body.appendChild(heart_box);

    const heartNodes = Array.from (heart_box.children);

    const f_update_positions = (() => {

        heartNodes.forEach (((xx: HTMLElement) => {
            xx["xxleft"] +=
                (() => {
                    const rnd = Math.random();
                    if ( rnd < 0.3333 ) {
                        return 0;
                    } else if ( rnd < 0.6666) {
                        return driftX;}
                    else {
                        return - driftX;
                    }
                }) ();

            xx["xxtop"] = xx["xxtop"] + ( (xx["xsize"]/20) * (gravity) );

            if ( xx["xxtop"] > (viewSpaceHeight) + viewSpaceHeight/10 ) {
                f_restart_heart(xx);
            } else {
                xx["xxtop"] = xx["xxtop"] + gravity /10 * randomInt(0,10); };

            if ( xx["xrotate"] !== 0 ) {
                xx["xrotate"] = xx["xrotate"] + randomInt(-30,60);
                xx.style.transform = "rotate(" + xx["xrotate"] + "deg)";
            };

            xx.style.left = xx["xxleft"] + "px";
            xx.style.top = xx["xxtop"] + "px";
        }))

    });

    setInterval( f_update_positions , update_speed);
}
;

How Does it Work?

The main thing is to create HTML elements with CSS that's fixed position with respect to window. Each element is a “heart” in its own layer. Then, just create a loop to update the element's positions.

CSS Layout

CSS Layers

JavaScript Using Css Layers

BUY
ΣJS
JavaScript in Depth

DOM Scripting

Overview

DOM Methods

Basic Examples

HTML Input

Web Scripting Examples

Web Scripting Misc