``````.heart-wrapper.active
.heart
.ring
.circles``````
``````@import "compass";

// Config
\$size: 10em;
\$animDuration: .8s;
\$animTiming: ease-in;
\$animIteration: 1;
\$animStep: 100% / 27;

// Layers & Colors
\$heartColors: #AAB8C2, #E2264D;
\$ringColors: #E2264D, #CC8EF5;
\$circles: (
(
first:   ( start: #8CE8C3, end:#A068CE),
second:  ( start: #8BE7C2, end:#B752E1)
),
(
first:   ( start: #90D2FA, end:#99E9C8),
second:  ( start: #91D1F9, end:#BAE3D7)
),
(
first:   ( start: #CC8EF5, end:#D3F491),
second:  ( start: #CB8DF4, end:#DCE483)
),
(
first:   ( start: #8CE8C3, end:#59C392),
second:  ( start: #8CE8C3, end:#67CD9F)
),
(
second:  ( start: #F48DA6, end:#959FF3)
),
(
first:   ( start: #91D2FA, end:#CA5ED8),
second:  ( start: #91D2FA, end:#A975D1)
),
(
first:   ( start: #92D3FC, end:#C35DD1),
second:  ( start: #CB8DF4, end:#90E0BE)
)
);

// Computations
\$circlesLength: length(\$circles);
\$angleBetweenCircles: 360deg / \$circlesLength;
\$circleSize: \$size / 6;
\$shiftAngleBeginning: -135deg;

// Functions
@function setStep(\$n) { @return (\$n - 1) * \$animStep }

@function setBoxShadow(\$distance1, \$distance2, \$size1, \$size2, \$shiftAngle, \$colorRatio) {
\$boxS: ();

@for \$i from 1 through length(\$circles) {
\$circle: nth(\$circles, \$i);
\$order: \$i - 1;
\$angle1: (\$order * \$angleBetweenCircles) + \$shiftAngleBeginning;
\$angle2: \$angle1 + \$shiftAngle;
\$distanceRatio1: \$size * \$distance1;
\$distanceRatio2: \$size * \$distance2;
\$firstCircle: map-get(\$circle, first);
\$firstCircleStart: map-get(\$firstCircle, start);
\$firstCircleEnd: map-get(\$firstCircle, end);
\$secondCircle: map-get(\$circle, second);
\$secondCircleStart: map-get(\$secondCircle, start);
\$secondCircleEnd: map-get(\$secondCircle, end);

\$boxS: append(\$boxS,
cos(\$angle1) * \$distanceRatio1
sin(\$angle1) * \$distanceRatio1
0
\$circleSize * \$size1
mix(\$firstCircleStart, \$firstCircleEnd, \$colorRatio)
);

\$boxS: append(\$boxS,
cos(\$angle2) * \$distanceRatio2
sin(\$angle2) * \$distanceRatio2
0
\$circleSize * \$size2
mix(\$secondCircleStart, \$secondCircleEnd, \$colorRatio)
);
}

@return join(\$boxS, (), "comma");
}

// Animations
@keyframes heart {
#{setStep(1)},
#{setStep(6)} {
transform: scale(0);
}
#{setStep(13)} {
transform: scale(1.25);
}
#{setStep(18)},
#{setStep(28)} {
transform: scale(1);
}
#{setStep(23)} {
transform: scale(1.025);
}
}

@keyframes ring {
#{setStep(1)} {
transform: scale(0);
box-shadow: inset 0 0 0 \$size*.85 nth(\$ringColors, 1);
}
#{setStep(2)} {
transform: scale(.1);
}
#{setStep(3)} {
transform: scale(.7);
}
#{setStep(4)} {
transform: scale(1);
}
#{setStep(5)} {
transform: scale(1.1);
box-shadow: inset 0 0 0 \$size*.85 nth(\$ringColors, 1);
}
#{setStep(6)} {
transform: scale(1.1);
box-shadow: inset 0 0 0 \$size*.5 nth(\$ringColors, 2);
}
#{setStep(7)} {
transform: scale(1);
box-shadow: inset 0 0 0 \$size*.085 nth(\$ringColors, 2);
}
#{setStep(8)},
#{setStep(28)} {
box-shadow: inset 0 0 0 0 nth(\$ringColors, 2);
}
}

@keyframes circles {
#{setStep(1)},
#{setStep(6)} {
box-shadow: setBoxShadow(\$distance1: 0.75, \$distance2: 0.75, \$size1: -0.500, \$size2: -0.500, \$colorRatio: 100%, \$shiftAngle:  -5deg);
}
#{setStep(7)} {
box-shadow: setBoxShadow(\$distance1: 0.80, \$distance2: 0.85, \$size1: -0.200, \$size2: -0.200, \$colorRatio: 100%, \$shiftAngle:  -5deg);
}
#{setStep(15)} {
box-shadow: setBoxShadow(\$distance1: 1.20, \$distance2: 1.00, \$size1: -0.100, \$size2: -0.350, \$colorRatio:  25%, \$shiftAngle: -12deg);
}
#{setStep(23)},
#{setStep(28)} {
box-shadow: setBoxShadow(\$distance1: 1.20, \$distance2: 1.00, \$size1: -0.500, \$size2: -0.500, \$colorRatio:   0%, \$shiftAngle: -12deg);
}
}

// Styles
.heart-wrapper{
height: \$size * 3;
width: \$size * 3;
position: relative;
cursor:pointer;

// Layer 1 : Heart
.heart{
\$_size: \$size * .8;
position: absolute;
height: \$_size;
width: \$_size;
top: 50%;
left: 50%;
z-index: 0;
margin-top: \$_size * -.5;
margin-left: \$_size * -.5;
background-color: nth(\$heartColors, 1);
visibility: hidden;

&::before,
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: (\$_size \$_size 0em \$_size*1.5) / (\$_size \$_size \$_size \$_size);
background-color: inherit;
visibility: visible;
}
&::before {
transform: translateX(-30%) rotateZ(30deg) skew(15deg);
}
&::after {
transform: translateX(30%) rotateZ(-30deg) rotateY(180deg) skew(15deg);
}
}

// Layer 2 : Ring
.ring{
display: block;
position: absolute;
top: 50%;
left: 50%;
width: \$size * 1.7;
height: \$size * 1.7;
margin-top: \$size * 1.7 * -.5;
margin-left: \$size * 1.7 * -.5;
z-index: 1;
}

// Layer 3 : Circles
.circles{
display: block;
position: absolute;
height: \$circleSize;
width: \$circleSize;
top: 50%;
left: 50%;
margin-top: -\$circleSize / 2;
margin-left: -\$circleSize / 2;
z-index: 2;
}

// Hover Styles
&:hover .heart{
background-color: nth(\$heartColors, 2);
}

// Active Styles
&.active{

// Layer 1 : Animation
.heart{
animation-name: heart;
animation-duration: \$animDuration;
animation-timing-function: \$animTiming;
animation-iteration-count: \$animIteration;
background-color: nth(\$heartColors, 2);
}

// Layer 2 : Animation
.ring{
animation-name: ring;
animation-duration: \$animDuration;
animation-timing-function: \$animTiming;
animation-iteration-count: \$animIteration;
}

// Layer 3 : Animation
.circles{
animation-name: circles;
animation-duration: \$animDuration;
animation-timing-function: \$animTiming;
animation-iteration-count: \$animIteration;
}
}
}

/* -------------------------------------------------- */
// LAYOUT
html{
font-size:8px;
}

@media (min-width: 768px) {
html{
font-size:16px;
}
}

body{
background: #fff;
margin:0;
}
.heart-wrapper{
position:absolute;
top:50%;
left:50%;
margin:(-\$size * 1.5) 0 0 (-\$size * 1.5);
}``````
``````window.onload = function(){
var debug = /*true ||*/ false;
var h = document.querySelector('.heart-wrapper');

function toggleActivate(){
h.classList.toggle('active');
}

if(!debug){
toggleActivate();
},false);

// setInterval(toggleActivate,1000);
}else{
var elts = Array.prototype.slice.call(h.querySelectorAll(':scope > *'),0);
var activated = false;
var animating = false;
var count = 0;
var step = 1000;

function setAnim(state){
elts.forEach(function(elt){
elt.style.animationPlayState = state;
});
}

if (animating) return;
if (count > 27) {
h.classList.remove('active');
count = 0;
return;
}
if (!activated) h.classList.add('active') && (activated = true);

console.log('Step : '+(++count));
animating = true;

setAnim('running');
setTimeout(function(){
setAnim('paused');
animating = false;
},step);
},false);

setAnim('paused');
elts.forEach(function(elt){
elt.style.animationDuration = step/1000*27+'s';
});
}

};
``````

### External CSS

This Pen doesn't use any external CSS resources.

### External JavaScript

This Pen doesn't use any external JavaScript resources.