Please have a look at this code snippet:
const highlight = (element) => {
element.classList.remove('highlight');
setTimeout(() => {
element.classList.add('highlight');
}, 0);
element.onanimationend = () => {
element.classList.remove('highlight');
}
}
document.querySelector('body').addEventListener('click', event => {
if (event.target.hash) {
event.preventDefault();
const element = document.querySelector(event.target.hash);
highlight(element);
}
});
@keyframes highlight {
from {
background: red;
}
to {
background: white;
}
}
.highlight {
animation: highlight 5s;
}
<ul>
<li>
<a href="#foo">Foo</a>
<div>
<ul>
<li>
<a href="#foo-1">Foo 1</a>
</li>
<li>
<a href="#foo-2">Foo 2</a>
</li>
<li>
<a href="#foo-3">Foo 3</a>
</li>
</ul>
</div>
</li>
<li>
<a href="#bar">Bar</a>
</li>
<li>
<a href="#baz">Baz</a>
</li>
</ul>
<hr>
<div id="foo">
<h2>Foo</h2>
<ul>
<li id="foo-1">Foo 1</li>
<li id="foo-2">Foo 2</li>
<li id="foo-3">Foo 3</li>
</ul>
</div>
<div id="bar">
<h2>Bar</h2>
</div>
<div id="baz">
<h2>Baz</h2>
</div>
Then please run the code snippet (preferably on full page) and try:
Click on “Foo”, wait a second or two, click on “Foo 1”, wait another second, click on “Foo 2”, wait a second, click on “Foo 2” again, wait a second, click on “Foo 3”. Everything works as expected.
Now click on “Foo 1” (or “Foo 2” or “Foo 3”), wait 3 seconds and then click on “Foo”. As you can see, the background color animation of “Foo” ends at the same time as the background color animation of “Foo 1” (or “Foo 2” or “Foo 3”). One could also say that the CSS class “highlight” is removed from “Foo” too early.
Why is that and how to fix this?