I'm trying to synchronize CSS animations for multiple page elements receiving the same animation class.
There seems to be a lot of posts about this subject but no unified solution, and none of the solutions I've found seem to apply to this case.
I've prepared a jsfiddle here to demonstrate the issue:
https://jsfiddle.net/gdf7szo5/1/
If you click on any of the letters it will start the animation for that letter. If you click again it will switch to a different animation, and if you click a third time it will set the letter to have no animation at all.
The desired effect is for all letters blinking in one animation to be synchronized with each other, and any letters in the other animation to be synchronized with each other. To be clear, I'm not trying to synchronize the two animations — I just want all the elements with a given animation to be synchronized with each other.
But currently if one letter shows an animation and you set another letter to the same animation, unless you have absolutely perfect timing the animations for the two letters will be out of sync even though they're the same animation.
Here's the code in play:
HTML:
<div>
<span id="spA" onclick="toggleFx('spA')">A</span>
<span id="spB" onclick="toggleFx('spB')">B</span>
<span id="spC" onclick="toggleFx('spC')">C</span>
<span id="spD" onclick="toggleFx('spD')">D</span>
</div>
CSS:
div {
display: flex;
flex-flow: column;
}
span {
animation-name: pulse_active;
}
span.pulse {
color: #f00;
animation: pulse_active 1.5s ease-in infinite;
}
span.pulse_invert {
color: #00f;
animation: pulse_inverted 3s ease-in infinite;
}
@keyframes pulse_active {
0% {
opacity: 0;
}
50% {
opacity: 0.66;
}
100% {
opacity: 0;
}
}
@keyframes pulse_inverted {
0% {
opacity: 1;
}
50% {
opacity: 0.33;
}
100% {
opacity: 1;
}
}
JS:
let pulseNormal = {};
let pulseInvert = {};
function toggleFx(spanID) {
let spanTarget = document.getElementById(spanID);
// shift setting
if (spanID in pulseInvert) {
console.log('y');
console.log(Object.keys(pulseInvert));
delete pulseInvert[spanID]
console.log(Object.keys(pulseInvert));
} else if (spanID in pulseNormal) {
pulseInvert[spanID] = true;
delete pulseNormal[spanID];
} else {
pulseNormal[spanID] = true
}
// update display
for (let sp of 'ABCD') {
let span = document.getElementById(`sp${sp}`);
// clear any prev animation
span.classList.remove('pulse');
span.classList.remove('pulse_invert');
// add/re-add animation as needed
if (`sp${sp}` in pulseNormal) {
span.classList.add('pulse');
} else if (`sp${sp}` in pulseInvert) {
span.classList.add('pulse_invert');
}
}
}