I’m animating a slide-in header. After a certain HTML element scrolls to the top of the page, a header is supposed to slide in. When the element is scrolled back away from the top of the page, it is supposed to slide out. The problem I’m having is that when the element reaches the top of the page, both animations happen at the same time.
The example is at https://codepen.io/scottthomason/pen/VwNZVLd. Here is the code for posterity. Make sure the browser output window is sized small enough to allow for scrolling.
HTML
<div class="header">
Header goes here.
</div>
<div class="content">
<h1>Content 1</h1>
<h1>Content 2</h1>
<h1 class="trigger">Content 3</h1>
<h1>Content 4</h1>
<h1>Content 5</h1>
<h1>Content 6</h1>
<h1>Content 7</h1>
<h1>Content 8</h1>
</div>
CSS
.header {
border: 3px solid green;
color: white;
background-color: red;
padding: 16px;
width: 100%;
position: fixed;
top: -60px;
opacity: 0;
animation-duration: 0.5s;
}
@keyframes fade-in {
from { top: -60px; opacity: 0; }
to { top: 0; opacity: 1; }
}
@keyframes fade-out {
from { top: 0; opacity: 1; }
to { top: -60px; opacity: 0; }
}
Javascript
let header = document.querySelector( '.header' );
let trigger = document.querySelector( '.trigger' );
window.addEventListener( 'scroll', function( e ) {
let topPos = trigger.getBoundingClientRect().top;
if ( topPos <= 10 ) {
console.log( 'Fading in, topPos:', topPos );
header.style.animationName = 'fade-in';
} else {
console.log( 'Fading out, topPos:', topPos );
header.style.animationName = 'fade-out';
}
} );
3
Answers
Whenever the browser executes an animation, it will revert back to the styles applied to the element previously. So in your case, it will play the
fade-in
animation just fine, but the applied styles are still the ones in your.header
class, which is in a hidden state.There are different ways to address this, such as separating the two styles in different classes and applying them through JS along with your animation class, but I would suggest a one-liner that will handle this for you. Just add
animation-fill-mode: forward;
to your.header
class and it will inform the browser to retain the computed values of your last keyframe.You can find more information on MDN.
You can use the shorthand animation and use the forwards for the animation not to return to initial state
The problem that arises because the header is going back to its initial state after the animation played.
Instead of using keyframes for your animation, you can use the
transition
attribute in your header and manipulate theopacity
andposition
with JavaScript.CSS:
JS: