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 thevisibility
andopacity
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
How to Stop Mobile Safari from Setting Fixed Positions to Absolute on Input Focus
Adding Class to Editorfor in MVC
Css3 Transition from Width Auto to "N" Px
Specifying Different Font-Sizes for Different Font-Families
Width Transitioning from Fixed Size to "Auto" Using CSS Without JavaScript
Animated CSS Underline on Delay
Bootstrap 3 Panel Header with Buttons Wrong Position
Can Someone Recommend a Bells and Whistles CSS Framework
How to Get Multiple Borders with Rounded Corners? CSS
How to Vertically Center Text in Its Bounding Box
Chrome/Firefox Percentage Height Differences in CSS Grid
How to Put Text Inside Radio Button
Want to Make the Whole Page in Grayscale Except Specified Div
Use Images in CSS Files with Reactjs
How to Change Primefaces Submenu Default Icons
How to Truncate String Inside a Direction Column Flexbox Child