The answer from @RokoC.Buljan about WAAPI Works great for animation where we don't care about reversing from in between and then the comment specifies taking the progress of the animation and then interpolating the new value. Thanks for the motivation.
After testing different stuff I came up with this solution that makes the animation similar to the CSS Transitions' animation. Below is the Code with explanation in comments:
<div class="container">
<div class="box"></div>
<button class="button">Click Me</button>
</div>
* {
box-sizing: border-box;
margin: 0;
}
body {
overflow: hidden;
}
.container {
background-color: black;
display: flex;
gap: 1.5rem;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.button {
background-color: #33b864;
border: none;
padding-inline: 2rem;
padding-block: 1rem;
scale: 1;
box-shadow: 0 0 0 0 #00000060;
transition: scale 100ms ease-in, box-shadow 100ms ease-in;
}
.button:hover {
scale: 1.05;
box-shadow: 0 0 3px 1px #00000060;
}
.button:touch {
scale: 2;
}
.button:active {
scale: 0.9;
}
/* Code that matters */
.box {
background-color: blue;
border: 2px solid red;
aspect-ratio: 1;
width: 200px;
}
/* .box-hover {
border: 6px solid green;
width: 250px;
background-color: purple;
} */
// Getting everything
const button = document.querySelector('.button');
const box = document.querySelector('.box');
// Keyframes
const keyframes = [
{ border: '2px solid red', width: '200px', backgroundColor: 'blue', offset: 0 },
{ border: '6px solid green', width: '250px', backgroundColor: 'purple', offset: 1 },
];
// Options
const options = {
duration: 800,
easing: 'ease-in',
fill: 'both',
};
// Creating animation and instantly pausing it.
const anim = box.animate(keyframes, options);
anim.pause();
// The play state automaticaly changes from finished to
// running even if only the sign of playbackRate is changed.
setInterval(() => {
console.log(anim.playState);
}, 100)
document.querySelector('.button').addEventListener('click', () => {
// Playing the animation for the first click and then
// After first iteration only setting the Animation.playbackRate *= -1
// or saying Animation.reverse() would make the animation change direction
// mid animation and also after the animation would be finished.
if(anim.playState === 'paused') {
anim.play();
} else {
anim.playbackRate *= -1;
// same as:
// anim.reverse();
}
});
PS @RokoC.Buljan Please let me know if my question was vague and/or if I can further improve the code above. Thanks :)