DEV Community

Discussion on: Make a beating heart using CSS: beginner-friendly tutorial

Collapse
 
larainnepasion profile image
La Rainne Pasion

Oh my gosh, please add sparkles and let me know how it goes!

Collapse
 
rolandixor profile image
Roland Taylor • Edited

FINALLY got around to this lol

<body>
    <div class="heart">
      <div class="sparkle">
      </div>
      <div class="sparkle">
      </div>
      <div class="sparkle">
      </div>
      <div class="sparkle">
      </div>
      <div class="sparkle">
      </div>
      <div class="sparkle">
      </div>
    </div>
  </body>
Enter fullscreen mode Exit fullscreen mode

body {
  align-items: center;
  display: flex;
  justify-content: center;
  height: 100vh;
}

@keyframes heartbeat {
  0% {
    opacity: 1;
    transform: rotate(-45deg) scale(1);
  }
  50% {
    opacity: .735;
    transform: rotate(-45deg) scale(.765);
  }
  100% {
    opacity: 1;
    transform: rotate(-45deg) scale(1);
  }
}

.heart {
  animation: heartbeat 1.8235s infinite;
  aspect-ratio: 1/1;
  height: 25vh;
  background-color: red;
  position: relative;
  transform: rotate(-45deg) scale(5);
}

.heart::after,
.heart::before {
  aspect-ratio: 1/1;
  background-color: red;
  border-radius: 50%;
  content: '';
  height: 25vh;
  position: absolute;
}

.heart::after {
  left: 12.5vh;
}

.heart::before {
  top: -12.5vh;
}

@keyframes sparkle {
  0% {
    border: 3px solid red;
    transform: scale(0);
  }
  50% {
    border: 1px solid white;
  }
  100% {
    border: 1px solid transparent;
    transform: scale(1) translateX(7.5vh) translateY(-7.5vh);
  }
}

.sparkle {
  animation: sparkle 2.75s infinite;
  aspect-ratio: 1/1;
  border-radius: 50%;
  position: absolute;
  width: 3.35vh;
  z-index: 1;
}

@keyframes sparklebars {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(0);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes sparklebars2 {
  0% {
    opacity: 1;
    transform: scale(1) rotate(90deg);
  }
  50% {
    opacity: 0;
    transform: scale(0) rotate(90deg);
  }
  100% {
    opacity: 1;
    transform: scale(1) rotate(90deg);
  }
}

.sparkle::after,
.sparkle::before {
  animation: sparklebars .5s infinite;
  background-color: white;
  content: '';
  height: 5px;
  inset: 50% -50% 0 -50%;
  position: absolute;
}

.sparkle:after {
  animation: sparklebars2 .5s infinite;
  transform: rotate(90deg);
}

.sparkle:nth-child(1) {
  inset: calc(50% - 2.5vh);
}

.sparkle:nth-child(2) {
  inset: calc(50% - 2.5vh) 0 calc(50% - 2.5vh) auto;
}

.sparkle:nth-child(3) {
  inset: 0 calc(50% - 2.5vh) calc(50% - 2.5vh) auto;
}

.sparkle:nth-child(4) {
  inset: 100% 25% auto calc(50% - 2.5vh);
}

.sparkle:nth-child(5) {
  inset: 75% 100% auto auto;
}

.sparkle:nth-child(6) {
  inset: 75% 50% auto auto;
}

Enter fullscreen mode Exit fullscreen mode

The result:

Image description

I didn't bother to add randomness to their positions since that would require JS (unless there's some new CSS features I missed lol). Some day when I'm not busy (or lazy), I might circle back to this and spruce it up some more, just for fun.