I have a page with a lot of interactivity going on. Clicking a button here changes the text and image over there... that kind of stuff. Just about everything is controlled by click handlers adding or removing CSS classNames to show or hide the appropriate content. Almost all of the animation is achieved with CSS transitions. Pretty straight forward.
But I have one element that requires a keyframe animation. Its default state is to be hidden until it's time for it to enter the UI... at which point it needs to have this CSS keyframe animation applied and stay in the last state the animation had it in.
For the sake of this example, let's just say that when Block A becomes visible (by clicking the button), the element in question, Block A1, needs to fade in (remember in my actual use case, the animation is more complicated and can't be achieved using transitions... it requires a keyframe animation) and then remain with the properties it had in the last frame of the animation: in this case opacity: 1
after the animation runs.
Right now, the only way I'm able to do this is to use javascript to set the opacity after the animation runs. This works but I can see it getting really messy/complicated when elements now have a style attribute overriding the styles set in the CSS rulesets. You can see this start to happen when you click the button again to hide the block and then AGAIN to show it... Block A1 is still set to opacity: 1
so the animation ha no effect after the 1st time around.
Is there a better way to do this?
const $btn = document.querySelector('button');
const $block = document.querySelector('.block-a');
const $blocka1 = document.querySelector('.block-a-1');
$btn.addEventListener('click', function() {
$block.classList.toggle("is-visible")
})
$blocka1.addEventListener('animationend', function() {
console.log('done');
this.style.opacity = 1;
})
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
button {
font-size: 32px;
margin-bottom: 24px;
cursor: pointer;
}
.block-a {
width: 25vw;
height: 50vh;
background-color: red;
padding: 20px;
color: #fff;
transform: translateY(150%);
transition: all .25s linear;
}
.block-a.is-visible {
transform: translateY(0);
transition: all .1s ease-in;
}
.block-a-1 {
font-size: 32px;
font-weight: bold;
color: white;
background-color: blue;
padding: 10px;
opacity: 0;
}
.block-a.is-visible .block-a-1 {
animation: fadeIn 2s linear 2s;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<button>Do Block 1</button>
<div class="block-a">
<span class="block-a-1">Block A-1</span>
<h1>Block A</h1>
</div>