Stop Animation from Replaying When Parent Switches from Display:None to Block

Stop animation from replaying when parent switches from display:none to block

Yes, animations will restart every time the display value is changed from none to something else.

As per W3C Spec: (emphasis is mine)

Setting the display property to ‘none’ will terminate any running animation applied to the element and its descendants. If an element has a display of ‘none’, updating display to a value other than ‘none’ will start all animations applied to the element by the ‘animation-name’ property, as well as all animations applied to descendants with display other than ‘none’.

There is no direct way to prevent this from happening because that is the intended behavior. You can workaround the situation by using other methods to hide the element instead of using display: none.

Following are a few suggestions on how the element could be hidden without display: none. It is not mandatory to use only one of the following workarounds, it could be some other way also as long as it doesn't involve changing the display property of the element.

  • Using height: 0, width: 0, overflow: hidden to hide the element.

    $(".toggler").on("click", function() {  $(".parent").toggleClass("active");});
    .parent {  height: 0;  width: 0;  overflow: hidden;  cursor: pointer;}.child {  width: 100px;  height: 100px;  background-color: red;  position: relative;  animation: move 200ms cubic-bezier(.91, .8, .54, 1.39) forwards;}.active {  height: auto;  width: auto;  overflow: visible;}.child.red {  background-color: red;}.child.blue {  background-color: blue;}@keyframes move {  from {    left: 0;  }  to {    left: 180px;  }}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><a class="toggler">Click this</a>
    <div class="parent active"> <div class="child red"></div></div>
    <div class="parent"> <div class="child blue"></div></div>

    Changing element's display from 'none' replays its animation

    Just remove the animate class after the first animation is completed.

    $(() => {  $('#test').addClass('animate');   setTimeout(() => {    $('#test').addClass('pause').css({ display: 'none' });    setTimeout(() => {      $('#test').css({ display: 'initial' });    }, 1000);  }, 1000);});
    #test {  visibility: hidden;  position: relative;  left: 0;}
    #test.animate { visibility: visible; animation: move 1s ease forwards;}
    #test.animate.pause { animation-play-state: paused;}
    @keyframes move { 0% { display: none; left: 100px; } 1% { display: inital; left: 0px; } 100% { left: 100px; }}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><img id="test" src="https://cdn4.buysellads.net/uu/1/3332/1524843316-62666.png">

    How to prevent a CSS keyframe animation from running on page load?

    Solution 1 - Add down animation on first hover

    Probably the best option is to not put the down animation on until the user has hovered over the container for the first time.

    This involves listening to the mouseover event then adding a class with the animation at that point, and removing the event listener. The main (potential) downside of this is it relies on Javascript.

    ;(function(){    var c = document.getElementById('container');    function addAnim() {        c.classList.add('animated')        // remove the listener, no longer needed        c.removeEventListener('mouseover', addAnim);    };
    // listen to mouseover for the container c.addEventListener('mouseover', addAnim);})();
    #container {    position:relative;    width:100px;    height:100px;    border-style:inset;}#content {    position:absolute;    top:100px;    width:100%;    height:100%;    background-color:lightgreen;    opacity:0;}
    /* This gets added on first mouseover */#container.animated #content { -webkit-animation:animDown 1s ease;}
    #container:hover #content { -webkit-animation:animUp 1s ease; animation-fill-mode:forwards; -webkit-animation-fill-mode:forwards;}
    @-webkit-keyframes animUp { 0% { -webkit-transform:translateY(0); opacity:0; } 100% { -webkit-transform:translateY(-100%); opacity:1; }}@-webkit-keyframes animDown { 0% { -webkit-transform:translateY(-100%); opacity:1; } 100% { -webkit-transform:translateY(0); opacity:0; }}
    <div id="container">    <div id="content"></div></div>

    Css transition from display none to display block, navigation with subnav

    As you know the display property cannot be animated BUT just by having it in your CSS it overrides the visibility and opacity transitions.

    The solution...just removed the display properties.

    nav.main ul ul {  position: absolute;  list-style: none;  opacity: 0;  visibility: hidden;  padding: 10px;  background-color: rgba(92, 91, 87, 0.9);  -webkit-transition: opacity 600ms, visibility 600ms;  transition: opacity 600ms, visibility 600ms;}nav.main ul li:hover ul {  visibility: visible;  opacity: 1;}
    <nav class="main">  <ul>    <li>      <a href="">Lorem</a>      <ul>        <li><a href="">Ipsum</a>        </li>        <li><a href="">Dolor</a>        </li>        <li><a href="">Sit</a>        </li>        <li><a href="">Amet</a>        </li>      </ul>    </li>  </ul></nav>

    Toggle CSS keyframes

    I would use a transition - see the comments in the css and js as to what I changed:

    var popup = document.getElementById("popup");var add = document.getElementById("add");var span = document.getElementById("close");add.onclick = function() {  popup.className = "opened";                // only need to transition the popup }span.onclick = function() {  popup.className = "closed";}window.onclick = function(event) {  if (event.target == popup) {    popup.className = "closed";  }}
    #popup {  position: fixed;  z-index: 1;  padding-top: 100px;  left: 0;  top: 0;  width: 100%;  height: 100%;  background-color: rgba(0, 0, 0, 0.4);    /* add the following and remove the display:none */  transition: opacity 0.6s;  opacity: 0;                /* start off closed and opacity 0 to hide */}#popup.opened {  opacity: 1;        /* add opacity 1 so it transitions to be shown */}
    #popup.closed { /* this stops the popup from overlaying the content when closed */ pointer-events:none;}
    #popup_content { position: relative; margin: auto; background-color: white; width: 80%; max-width: 500px; border-radius: 5px; padding: 20px; text-decoration: none; box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.5);}

    #close { float: right; cursor: pointer; margin: -15px -15px 0 0;}
    <button id="add">Open popup</button>

    <div class="closed" id="popup"> <div id="popup_content"> <i class="fas fa-times-circle" id="close">Close</i> //////content </div></div>

    Pure CSS animation visibility with delay

    You are correct in thinking that display is not animatable. It won't work, and you shouldn't bother including it in keyframe animations.

    visibility is technically animatable, but in a round about way. You need to hold the property for as long as needed, then snap to the new value. visibility doesn't tween between keyframes, it just steps harshly.

    .ele {  width: 60px;  height: 60px;    background-color: #ff6699;  animation: 1s fadeIn;  animation-fill-mode: forwards;    visibility: hidden;}
    .ele:hover { background-color: #123;}
    @keyframes fadeIn { 99% { visibility: hidden; } 100% { visibility: visible; }}
    <div class="ele"></div>

    Override CSS Display property with Flexslider 2

    As per the js-fiddle you shared the problem can be solved by the following approach-

    Toggle the hide-me class first and then initialize flexslider with the selector ".slides > li:not(.hide-me)".
    This we are doing so that we can select appropriate images as per your requirement. Now all the width calculations done by flexslider will be based on the images that are visible i.e. that don't have the "hide-me" class. The :not(selector) selector here matches every element that is NOT the specified element/selector.

      $(function() {
    /* Toggle hide-me class*/
    var $liCarousel = $('#carousel_container li.img');
    $liCarousel.toggleClass('hide-me');
    $liCarousel.siblings('[data-ingal-order=1]').toggleClass('hide-me');

    $('#carousel_container').flexslider({
    animation: "slide",
    controlNav: false,
    animationLoop: false,
    slideshow: false,
    itemWidth: 210,
    itemMargin: 5,
    asNavFor: 'div#slider_container',
    selector: '.slides > li:not(.hide-me)'
    });

    $('div#slider_container').flexslider({
    animation: "slide",
    controlNav: false,
    animationLoop: false,
    directionNav:false,
    slideshow: false,
    sync: 'div#carousel_container'
    });
    });

    How can I stop a CSS animation on scroll?

    I was able to fix this by replacing 'window' with my content wrapper. Like this:

    jQuery('#wrapper').scroll(function() {
    jQuery('.arrow').css("display", "none");
    });


    Related Topics



Leave a reply



Submit