Reputation:
https://jsfiddle.net/elgs/580nhepk/11/
This tiny demo is trying to slide up/down a div with the ease-in
timing/easing function. However, it seems the easing effect is only effective the first time it slides down. From the second time onward, the easing effect seems to be disappeared.
HTML
<button id='slideup'>Slide Up</button>
<button id='slidedown'>Slide Down</button>
<div id="a"></div>
Javascript
const a = document.querySelector('div#a');
const u = document.querySelector('button#slideup');
const d = document.querySelector('button#slidedown');
u.addEventListener('click', (e) => {
a.style.setProperty('--height', '30px');
a.classList.add('slide');
});
d.addEventListener('click', (e) => {
a.style.setProperty('--height', '100px');
a.classList.add('slide');
});
CSS
div#a {
width: 100px;
height: 100px;
box-sizing: border-box;
border: 1px solid gray;
}
@keyframes slide {
to {
height: var(--height);
}
}
.slide {
animation-name: slide;
animation-duration: .4s;
animation-timing-function: ease-in;
animation-delay: 0s;
animation-direction: normal;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: running;
}
Upvotes: 2
Views: 665
Reputation: 51
css animation usully execute animation at the first time when the page has loaded. In this situation,you should use css transition instead of css animation for Example:
.slide-up {
height : 30px;
}
.slide-down {
height : 60px;
}
#a{
transition: height 200ms
}
Upvotes: 0
Reputation: 137133
This is because you've set your animation to run only once, so it won't run again after, unless you remove the animated class from the element every time + trigger a reflow + update its height property.
const a = document.querySelector('div#a');
const u = document.querySelector('button#slideup');
const d = document.querySelector('button#slidedown');
u.addEventListener('click', (e) => {
a.style.setProperty('height', '100px'); // so the animation knows the 'from' value
a.style.setProperty('--height', '30px');
a.classList.remove('slide'); // so the animation starts again
a.offsetHeight; // so the no-class be calculated
a.classList.add('slide');
});
d.addEventListener('click', (e) => {
a.style.setProperty('height', '30px');
a.style.setProperty('--height', '100px');
a.classList.remove('slide');
a.offsetHeight;
a.classList.add('slide');
});
div#a {
width: 100px;
height: 100px;
box-sizing: border-box;
border: 1px solid gray;
}
@keyframes slide {
to {
height: var(--height);
}
}
.slide {
animation-name: slide;
animation-duration: .4s;
animation-timing-function: ease-in;
animation-delay: 0s;
animation-direction: normal;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: running;
}
<button id='slideup'>Slide Up</button>
<button id='slidedown'>Slide Down</button>
<div id="a"></div>
But anyway, what you want is not an animation but a transition:
const a = document.querySelector('div#a');
const u = document.querySelector('button#slideup');
const d = document.querySelector('button#slidedown');
u.addEventListener('click', (e) => {
a.style.setProperty('--height', '30px');
});
d.addEventListener('click', (e) => {
a.style.setProperty('--height', '100px');
});
div#a {
width: 100px;
height: 100px;
height: var(--height, 100px);
box-sizing: border-box;
border: 1px solid gray;
}
.slide {
transition: height .4s ease-in;
}
<button id='slideup'>Slide Up</button>
<button id='slidedown'>Slide Down</button>
<div id="a" class="slide"></div>
Upvotes: 2