JSFiddle - React, Tailwind, and code Playground
Using CSS variables to control start and end of CSS keyframes animation.
by Travis Almand
HTML
<div id="top" class="target" data-loc="0,-100px,0"></div>
<div id="right" class="target" data-loc="100px,0,0"></div>
<div id="bottom" class="target" data-loc="0,100px,0"></div>
<div id="left" class="target" data-loc="-100px,0,0"></div>
<div id="box"></div>
CSS
:root {
--start: translate3d(0, 0, 0);
--end: translate3d(0, 0, 0);
}
.target {
background: gainsboro;
bottom: 0;
cursor: pointer;
height: 50px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 50px;
}
#top { top: -200px; }
#right { right: -200px; }
#bottom { bottom: -200px; }
#left { left: -200px; }
#box {
background: black;
bottom: 0;
height: 20px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 20px;
}
#box.animate {
animation-duration: 1s;
animation-fill-mode: forwards;
animation-name: animate;
animation-timing-function: linear;
}
@keyframes animate {
0% {
transform: var(--start);
}
50% {
transform: translate3d(0, 0, 0);
}
100% {
transform: var(--end);
}
}
JavaScript
var $box = document.querySelector('#box');
var $top = document.querySelector('#top');
var $right = document.querySelector('#right');
var $bottom = document.querySelector('#bottom');
var $left = document.querySelector('#left');
var $targets = document.querySelectorAll('.target');
function animate (event) {
var $this = event.currentTarget
var current = window.getComputedStyle($box).getPropertyValue('transform');
if (!$this.classList.contains('active')) {
for(var i = 0; i < $targets.length; i++) {
$targets[i].classList.remove('active');
}
$this.classList.add('active');
$box.classList.remove('animate');
void $box.offsetWidth;
$box.classList.add('animate');
document.documentElement.style.setProperty('--start', current);
document.documentElement.style.setProperty('--end', 'translate3d(' + $this.dataset.loc + ')');
}
}
$top.addEventListener('click', animate);
$right.addEventListener('click', animate);
$bottom.addEventListener('click', animate);
$left.addEventListener('click', animate);