Trinkets, roses and sweets, you can smell the love spreading in the air. It is again close to one of the most romantic holidays of the year. Today I will show you a way to cultivate your website with some lovely atmosphere. Coding is easy, so have no fear.

Shen Huang
Feb 13 · 6 min read

In this tutorial we will be trying to accomplish the following tricks with Java Script and CSS animations. Hearts pop up by holding your mouse key or finger on a touch screen, and follows your movement. A web demo can also be found here. I have also invented a different way to draw hearts, requiring less components, which you will be reading it very soon.

Trails of Floating Hearts Demo

1. I knew you felt the same when I saw the rosiness on your cheeks…

Now Let’s get started! First of all, you will need a website. If you do not wish to use one of your own, copy the following code and save it as a .html file will do the job.

<!--Copyright to Shen Huang, you can reach me out at><!DOCTYPE html>
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<title>HEART DEMO</title>
body {
background-color : #ffceed;

2. It takes two to find love, and to merge hearts to one…

Now we need to draw the heart, a typical online tutorial will show you how to draw a heart in 3 parts, with 2 circles and a diamond. In this tutorial we do it with 2 rounded rectangles instead, each rotated by 45 degrees and placed symmetrical to each other.

Drawing CSS Heart with 2 Parts

The following CSS scripts will do the job if you place them between the <style></style> tags of your webpage, I also preferred #fc2a62 more than pure red for the heart because I think rosy pink is more romantic.

.heart {
z-index : 999;
position : absolute;
.heart:after {
content : "";
background-color : #fc2a62;
position : absolute;
height : 30px;
width : 45px;
border-radius : 15px 0px 0px 15px;
.heart:before {
transform : rotate(45deg);
.heart:after {
left : 10.5px;
transform : rotate(135deg);

In order to test our code, we can place the following code between the <body></body> tags of our webpage.

<div class = "heart"></div>

After you save and reload, you should see a heart displaying on the top left corner.

CSS Heart

3. Our heart melts, like snowflakes under the sun of April…

Now we have to make the heart slowly fade away, in order to do so we can define the following animations above our CSS scripts.

@keyframes heartfade {
0% {
opacity : 1;
50% {
opacity : 0;

And we also have to twitch our script defining the heart a little bit to make it accept the animation.

.heart {
z-index : 999;
animation : heartfade 6s linear;
position : absolute;

After save and reload we should see the heart fading.

Heart Fades

And now we can start working on our Java Script animations, all the following code should be placed between the <script></script> tags.

We have to first be able to create the hearts dynamically through scripting, the following scripts will do the job.

var brd = document.createElement("DIV");
document.body.insertBefore(brd, document.getElementById("board"));
const duration = 3000;
const speed = 0.5;
const cursorXOffset = 0;
const cursorYOffset = -5;
var hearts = [];
function generateHeart(x, y, xBound, xStart, scale)
var heart = document.createElement("DIV");
heart.setAttribute('class', 'heart');
heart.time = duration;
heart.x = x;
heart.y = y;
heart.bound = xBound;
heart.direction = xStart; = heart.x + "px"; = heart.y + "px";
heart.scale = scale; = "scale(" + scale + "," + scale + ")";
if(hearts == null)
hearts = [];
return heart;

If you are interested in what the code does, allow me to explain. The variable brd is basically an element for the hearts to attach to, which in the case you append it onto your own website you can change the element ID to make it append onto any arbitrary element.

The duration defines the millisecond time the heart should exist. And speed defines how fast the heart should move around. The cusorXOffset and cursorYOffset allows the heart to be instantiated in the correct position, which you will see it come in handy later. The hearts[] array keeps track of all the hearts.

Inside our generateHeart() function, the x and y defines the horizontal and vertical position of the heart. xBound defines how wide it can wiggle horizontally and xStart defines which direction it should start wiggle. The scale defines the size of the heart.

Now in order to see if we are on the right track, append the following code to the end for testing.

generateHeart(300, 300, null, null, 1);

After save and reload we should see a heart fading at x:300, y:300.

Heart Fading at x:300, y:300

4. And sometimes our hearts wiggle together…

Now we have to create our animation controller, the following code will do the job.

var before =;
var id = setInterval(frame, 5);
function frame()
var current =;
var deltaTime = current - before;
before = current;
for(i in hearts)
var heart = hearts[i];
heart.time -= deltaTime;
if(heart.time > 0)
heart.y -= speed; = heart.y + "px"; = heart.x + heart.direction * heart.bound * Math.sin(heart.y * heart.scale / 30) + "px";
hearts.splice(i, 1);

The animation controller basically just recalculates the position of the heart every 5 milliseconds, resulting a frame rate of 200 fps. The secret code inside the controller allows the heart to wiggle up in a sinusoidal fashion. The bigger the heart, the wider it wiggles.

Now we should see the heart floating up and wiggling after save and reload.

Heart Wiggling Up

5. In the end, my heart goes where ever you go…

Finally, we can now make the heart appear while the mouse key or the finger is held on the screen. Appending the following code will do the job.

var down = false;
var event = null;
document.onmousedown = function(e) {
down = true;
event = e;
document.onmouseup = function(e) {
down = false;
document.onmousemove = function(e) {
event = e;
document.ontouchstart = function(e) {
down = true;
event = e.touches[0];
document.ontouchend = function(e) {
down = false;
var gr = setInterval(check, 100);
function check()
var start = 1 - Math.round(Math.random()) * 2;
var scale = Math.random() * Math.random() * 0.8 + 0.2;
var bound = 30 + Math.random() * 20;
generateHeart(event.pageX - brd.offsetLeft + cursorXOffset, event.pageY - brd.offsetTop + cursorYOffset, bound, start, scale);

The code basically generates hearts at the cursor location every 100 milliseconds when the key or finger is held. The secret algorithm generates hearts of appropriate shape and size at random.

Now after save and reload we should see the following like we have seen at the beginning of the article.

Holding Mouse Key leaves a Trail of hearts

6. Moreover…

I have also created a CODEPEN below which you can try it yourself. I will be attaching the full code of this project in the appendix.

In the future I may write more relating to special effects like this one. Let me know what you are interested to see. I have also written some other articles in the past if you are interested reading.



Hope you have a great Valentine(s)!!!

Appendix (Complete Code of this Project):

Frontend Weekly

It's really hard to keep up with all the front-end development news out there. Let us help you. We hand-pick interesting articles related to front-end development. You can also subscribe to our weekly newsletter at

Shen Huang

Written by

Working on my thesis and job hunt, will blog more afterwards, offer me a job if you are interested.

Frontend Weekly

It's really hard to keep up with all the front-end development news out there. Let us help you. We hand-pick interesting articles related to front-end development. You can also subscribe to our weekly newsletter at

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade