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

倖福魔咒の 提交于 2019-12-01 06:53:21

问题


I have a set of tabs that each contain a child element that animates. What happens when I click each tab is that the animation of the child element within the tab runs. I do not want it to run. I want the animation to run the first time then not replay when it's parent switch from display:none to display:block.

In the example I made below I have 2 parent divs, each with a child div that animates over to the right. When each parent is set to block the animation replays, I do not want that to happen. I want each child to stay positioned over to the right. How can I make that happen?

$(".toggler").on("click", function() {
  $(".parent").toggleClass("active");
});
.parent {
  display: none;
  cursor: pointer;
}
.child {
  width: 100px;
  height: 100px;
  background-color: red;
  position: relative;
  animation: move 200ms cubic-bezier(.91, .8, .54, 1.39);
}
.active {
  display: block;
}
.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>

Fiddle Demo


回答1:


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>
  • Adding a container, using position: absolute and opacity: 0 to hide the element.

    $(".toggler").on("click", function() {
      $(".parent").toggleClass("active");
    });
    .container {
      position: relative;
    }
    .parent {
      position: absolute;
      opacity: 0;
      cursor: pointer;
    }
    .child {
      width: 100px;
      height: 100px;
      background-color: red;
      position: relative;
      animation: move 200ms cubic-bezier(.91, .8, .54, 1.39) forwards;
    }
    .active {
      opacity: 1;
    }
    .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='container'>
      <div class="parent active">
        <div class="child red"></div>
      </div>
    
      <div class="parent">
        <div class="child blue"></div>
      </div>
    </div>
  • Adding a container, using position: absolute and visibility: hidden to hide the element.

    $(".toggler").on("click", function() {
      $(".parent").toggleClass("active");
    });
    .container {
      position: relative;
    }
    .parent {
      position: absolute;
      visibility: 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 {
      visibility: 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='container'>
      <div class="parent active">
        <div class="child red"></div>
      </div>
    
      <div class="parent">
        <div class="child blue"></div>
      </div>
    </div>
  • Adding a container, using position: absolute and z-index to hide the element.

    $(".toggler").on("click", function() {
      $(".parent").toggleClass("active");
    });
    .container {
      position: relative;
    }
    .parent {
      position: absolute;
      z-index: -1;
      cursor: pointer;
    }
    .child {
      width: 100px;
      height: 100px;
      background-color: red;
      position: relative;
      animation: move 200ms cubic-bezier(.91, .8, .54, 1.39) forwards;
    }
    .active {
      z-index: 1;
    }
    .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='container'>
      <div class="parent active">
        <div class="child red"></div>
      </div>
    
      <div class="parent">
        <div class="child blue"></div>
      </div>
    </div>


来源:https://stackoverflow.com/questions/37664508/stop-animation-from-replaying-when-parent-switches-from-displaynone-to-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!