Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

rodrigoantunes-me/floating-hearts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

Out of the Blue: Creating Floating Hearts with a Range Slider with CSS and JavaScript

dev.to

Demo

CodePen

Post

Inspired by an animation I saw this morning, I decided to try creating something along those lines — though not nearly as impressive — using JavaScript 🎨. It seemed like a fun and challenging task.

So, let's dive in!

HTML

We'll start with a simple structure:

<main>
  <input type="range" min="0" max="100" value="0" />
  <div class="container"></div>  <!-- this is where we'll place the hearts -->
</main>

CSS

The CSS plays a significant role in this project, and I'd like to highlight two key aspects:

  • Accent Color
  • CSS Animations

Accent Color

I couldn't remember how to change the default look of the <input type="range" /> element. During my research, I came across various vendor-prefixed pseudo-elements like ::-webkit-slider-runnable-track and ::-moz-range-track but the support for these wasn't great.

Then I came across a handy little CSS property called accent-color. I had seen it a couple of times before, but not often enough for it to stick in my memory. It's also a perfect fit for styling checkbox and radio input elements.

Good job, CSS Working Group! 🥳

input {
  /* ... */
  accent-color: white;
}

CSS Animations

I usually enjoy coding CSS animations from scratch, fine-tuning them to align with the design goals or specific creative direction. But today, I wasn't feeling it, so I asked ChatGPT to write three organic floating animations with some variations and randomness. It didn't nail it on the first try, so instead of tweaking the animations by hand, I modified the prompt. While it might have been faster to code manually, after some time, the result was good enough.

edit: I fine-tuned the animations 😁

The one thing I was particularly picky about was the syntax. Initially, it generated something like this:

0% {
  transform: translateX(0px) translateY(0px) rotateX(45deg) rotateY(30deg) scale(0.25);
}

My reaction was like Michael Scott’s famous "Oh God, Please No!" meme. The CSS Transform Module Level 2 syntax looks so much cleaner:

0% {
  translate: 0px 0px;
  rotate: 45deg 30deg;
  scale: 0.25;
}

But I'm still getting used to this 'new' syntax too, so no big problems here.

Javascript

Okay, let's fire up the engine 🚛.

I found it challenging to explain my thought process, but I spent nearly an hour just thinking through the problem. Here’s a breakdown of my approach:

1. Listen to the input event.
2. Create a new element when the event fires.
3. Animate each element up from where the input is located.
4. Remove each element after it finishes animating.

However, there’s no straightforward way to determine where the "slider's thumb" is on the screen, just the input element itself. Turns out there was a simple solution to this:

range.addEventListener('input', (e) => {
  // ...
  const heart = document.createElement('div');
  heart.style.left = `${e.target.value}%`;
  // ...
}

Feel free to check out the code.

I could refine the code for readability, structure it better with functional programming, or even enhance the animations further, but it serves its purpose well for a quick experiment.

I hope you enjoy it, and happy coding!

A big thanks to Chris Gannon for his inspiring work.