Toggle bomb animation with delayed CSS variable
by AntowaKartowa
HTML
<style>
@property --bomb-angle {
syntax: "<angle>";
inherits: true;
initial-value: 0deg;
}
@property --delayed {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --fuse-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.bomb {
transition:
--bomb-angle var(--parent-easing) var(--parent-duration);
transform: rotate(var(--bomb-angle));
transform-origin: 9px 15px;
&.is-booped {
--bomb-angle: 15deg;
}
}
.fuse {
transition:
--delayed 0.2s ease-in,
transform 0.1s ease-out;
--delayed: var(--bomb-angle);
--fuse-angle: clamp(-45deg, calc(var(--delayed) - var(--bomb-angle)) * 2, 45deg);
transform: rotate(var(--fuse-angle));
transform-origin: 18px 6px;
}
</style>
<button class="wrapper">
<svg viewBox="0 0 24 24">
<g class="bomb">
<path
class="fuse"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m20.468 1.037-.466 2.96 2.96-.468-2.96.472 1.361 2.671L20 4.003 17 7l2.998-3-2.67-1.36 2.671 1.357z"
/>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-width="2"
d="M13.444 8.347A8 8 0 1 0 15.93 11"
/>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m12.359 7.649 1.06-1.061a2 2 0 0 1 2.829 0l1.414 1.414a2 2 0 0 1 0 2.829l-1.06 1.06"
/>
</g>
</svg>
</button>
CSS
html {
/* Stiffness: 300. Damping: 10 */
--parent-easing: linear(0, 0.011, 0.045 1.7%, 0.181 3.6%, 0.896 9.8%, 1.136 12.4%, 1.283 14.7%, 1.325, 1.347 17.2%, 1.351, 1.347, 1.334, 1.313 20.6%, 1.249 22.6%, 1.052 27.4%, 0.969 29.7%, 0.907 32.3%, 0.889, 0.879 35%, 0.878 36.7%, 0.89, 0.913 40.6%, 0.981 45.3%, 1.01 47.6%, 1.032, 1.042 52.7%, 1.043 54.5%, 1.039 56.5%, 0.997 65.4%, 0.989, 0.986 70.2% 74.4%, 1.001 83%, 1.005 87.3% 92%, 1);
--parent-duration: 1.167s;
/* Stiffness: 400. Damping: 10 */
--child-easing: linear(0, 0.012, 0.049 1.1%, 0.2 2.3%, 0.982 6.2%, 1.234, 1.385 9.1%, 1.425, 1.443, 1.442, 1.429 11.7%, 1.363 13%, 1.004 17%, 0.892 18.6%, 0.829 20%, 0.811, 0.803 21.4% 21.9%, 0.809 22.5%, 0.838 23.8%, 0.998 27.9%, 1.048, 1.076, 1.087, 1.085, 1.072 34.6%, 1.001 38.7%, 0.979, 0.966, 0.961 42.9%, 0.962, 0.966 45%, 1.007 50.6%, 1.014, 1.017 53.6%, 1.015 55.8%, 0.997 61.4%, 0.992 64.4%, 1.003, 0.999 85.7%, 1);
--child-duration: 1.5s;
}
body {
height: 100vh;
height: 100svh;
display: grid;
place-content: center;
border: 1px solid hsl(210deg 15% 25%);
border-radius: 4px;
background: hsl(210deg 15% 6%);
color: white;
/*
Don't add scrollbars if the rotation
forces the element beyond the edge
of the viewport:
*/
overflow: hidden;
}
.wrapper {
position: relative;
width: 100px;
height: 100px;
background: transparent;
border: none;
color: white;
cursor: pointer;
}
svg {
display: block;
width: 100%;
height: 100%;
fill: none;
overflow: visible;
}
JavaScript
const wrapper = document.querySelector('button');
const bomb = document.querySelector('.bomb');
wrapper.addEventListener('mouseenter', () => {
bomb.classList.add('is-booped');
window.setTimeout(() => {
bomb.classList.remove('is-booped');
}, 150);
});