9

I have an animation where a div slides out the view, however when the animation is completed, the div just returns to its origin position in the view. How do I totally remove the div or hide it after the animation ends using just CSS?

Here is the markup:

  <div class="container">
    <div class="slide-box" id="slide-box""></div>
  </div>

and the css:

.slide-box {
  position: relative;
  width: 100px;
  height: 100px;
  background-image: url(../pics/red.png);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;

  animation: slide 5s linear 1;
}
@keyframes slide {
  0% {
    left: 0;
  }
  20% {
    left: 20%;
  }
  40% {
    left: 40%;

  }
  60% {
    left: 60%;

  }
  80% {
    left: 80%;
  }
  100% {
    left: 100%;
    overflow: hidden;
    visibility: hidden;
  }
}

I don't want it to fade out over the duration of the animation, i just want it to disappear once it hits 100% in the keyframe. Thanks ahead of time!

Jared Garcia
  • 751
  • 1
  • 8
  • 17
  • Possible duplicate of [Stopping a CSS3 Animation on last frame](http://stackoverflow.com/questions/4359627/stopping-a-css3-animation-on-last-frame) – Alexander O'Mara Aug 29 '16 at 03:29

3 Answers3

13

Use the animation-fill-mode option. Set it to forwards and the animation ends at it's final state and stay like that.

Altered based upon comments Set opacity fade to just last 1% of animation... simplified keyframes. Added a jquery option to literally remove the div from the DOM. CSS alone won't alter the markup, where jQuery will.

Although you can't animate the display property. If you want the div totally gone, after the opacity fades to zero, you can then add the display property to remove the div. If you don't wait for opacity to end, the div will just vanish without any transition.

/* 

This jquery is added to really remove 
the div. But it'll essentially be 
VISUALLY gone at the end of the 
animation. You can not use, or 
delete the jquery, and you really 
won't see any difference unless 
you inspect the DOM after the animation.

This function is bound to animation 
and will fire when animation ends. 
No need to "guess" at timeout settings. 
This REMOVES the div opposed to merely 
setting it's style to display: none;  

*/

$('.slide-box').bind('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(e) { $(this).remove(); });
.slide-box {
  display: block;
  position: relative;
   left: 0%;
  opacity: 1;
  width: 100px;
  height: 100px;
  background: #a00;
  animation: slide 1s 1 linear forwards;
  
  /*
 animation-name: slide;
 animation-duration: 1s;
 animation-iteration-count: 1;
 animation-timing-function: linear;
 animation-fill-mode: forwards;
 */
}

@keyframes slide {
  0% {
   left: 0%;
  opacity: 1;
  }
  99% {
    left: 99%;
    opacity: 1;
  }
  100% {
    left: 100%;
    opacity: 0;
    display: none;
  }
}

@-webkit-keyframes slide {
  0% {
    left: 0%;
  opacity: 1;
  }
  99% {
    left: 99%;
    opacity: 1;
  }
  100% {
    left: 100%;
    opacity: 0;
    display: none;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <div class="slide-box" id="slide-box"></div>
  </div>
Scott
  • 21,475
  • 8
  • 43
  • 55
2
animation: slide 5s linear forwards;

at 100%

opacity: 0;
display: none;

Try this.

Working fiddle: https://jsfiddle.net/jbtfdjyy/1/

UPDATE: JS mani

var slideBox = document.getElementById('slide-box');

setTimeout(function(){
    slideBox.style.display = 'none';
}, 5000); 

Try this. https://jsfiddle.net/jbtfdjyy/2/

hdotluna
  • 5,514
  • 4
  • 20
  • 31
1

Add something at 99% or so to your keyframes, and set opacity to 1 in that. If you have opacity: 1 at the start, then it will stay that way until 99%. Only at 100% will it change.

It's not technically fired at 100%. If you want that, I'd recommend using some JavaScript here, but this will at least give the illusion you want.

@keyframes slide {
  0% {
    left: 0;
  }
  20% {
    left: 20%;
  }
  40% {
    left: 40%;
  }
  60% {
    left: 60%;
  }
  80% {
    left: 80%;
  }
  99% {
    opacity: 1;
  }
  100% {
    left: 100%;
    overflow: hidden;
    opacity: 0;
    display: none;
    visibility: hidden;
  }
}

UPDATE:

As per your request, here is a JavaScript version. Keep in mind, there are endless ways to accomplish such a task. I am using vanilla JS (no jQuery, etc.), and using ES6 syntax.

What we do here is set a timeout, and at the end of that timeout I broadcast an event animation_end. That event listener will handle the end of the animation (in this case, it adds a class which will handle the fading out). This is much more granular than you need it to be, you could simply do the adding of the class within the setTimeout, but I think it is slightly better this way as you can abstract you can do other things with events such as animation start, etc.

Here is the fiddle: https://jsfiddle.net/vmyzyd6p/

HTML:

<div class="container">
  <div class="slide-box" id="slide-box""></div>
</div>

CSS:

.slide-box {
  position: relative;
  width: 100px;
  height: 100px;
  background-color: blue;
  animation: slide 3s linear 1;
  -webkit-transition: opacity 2s ease-in-out;
  -moz-transition: opacity 2s ease-in-out;
  transition: opacity 2s ease-in-out;
}
.animationEnd {
  opacity: 0;
}
@keyframes slide {
  0% {
    left: 0;
  }
  20% {
    left: 20%;
  }
  40% {
    left: 40%;

  }
  60% {
    left: 60%;

  }
  80% {
    left: 80%;
  }
  100% {
    left: 100%;
  }
}

JavaScript:

// Create a function that handles the `animation_end` event
const animationEnd = () => {
    // Grab the slidebox element
    let slideBox = document.getElementById('slide-box');

    // Get the class of the slidebox element
    let slideClass = slideBox.getAttribute('class');

    // Add the animation end class appended to the previous class
    slideBox.setAttribute('class', slideClass + ' animationEnd');
};

// Create the animation end event
let animationEndEvent = new Event('animation_end');

// Cross browser implementation of adding the event listener
if (document.addEventListener) {
    document.addEventListener('animation_end', animationEnd, false);
} else {
    document.attachEvent('animation_end', animationEnd);
}

// Set the timeout with the same duration as the animation. 
setTimeout(() => {
        // Broadcast the animation end event
        document.dispatchEvent(animationEndEvent);
}, 3000);
Lansana Camara
  • 9,497
  • 11
  • 47
  • 87
  • What kind of js statement ? – Jared Garcia Aug 29 '16 at 03:50
  • 1
    I've updated my answer and included a Fiddle. Keep in mind, my approach was much more than you asked. You could've done this in 3 lines with a simple setTimeout, similar to what Herm Luna showed, but this approach allows you to handle a wider variety of things in my opinion and is a better approach (but there are still probably better approaches). – Lansana Camara Aug 29 '16 at 04:43
  • Cool! This is a great vanilla JS approach which I really like! Thanks – Jared Garcia Aug 29 '16 at 08:03